如何在Spark中的执行程序级别创建连接池?

时间:2015-10-30 14:48:20

标签: apache-spark

我希望在我的spark执行器中与第三方服务共享一个http连接池。

- 如果我在地图中创建连接池

,当然会为每个元素重新创建
from urllib3 import HTTPConnectionPool

rdd = sc.parallelize(["peter", "john", "harris"])


def get_service(name):
    pool = HTTPConnectionPool('ajax.googleapis.com', maxsize=10)

    r = pool.request('GET', '/ajax/services/search/web', fields={'q': 'urllib3', 'v': '1.0'})
    return name

rdd.map(lambda x: get_service(x)).count()
  • 如果我将其创建为全局函数,我会收到错误
  • 我可以做一个地图分区并在里面创建它。然后,我将通过分区获得一个连接池(总比没有好,但不完美)

我应该在哪里定义我的连接池,只有一个由执行者?

1 个答案:

答案 0 :(得分:2)

正如文档@ReactorMonk已经明确定义了foreachPartition内部的连接池(仅用于操作)或mapPartitions(如果您想要回复信息)是一种限制自己的好方法每个分区一个连接。 (虽然提供的链接是针对流式文档的,但它可能有点令人困惑,您可能还希望在https://spark.apache.org/docs/latest/api/python/pyspark.html#pyspark.RDD中查看mapPartitions

def processRecords(itr):
    pool = HTTPConnectionPool('ajax.googleapis.com', maxsize=10)
    return map(lambda name: //logic goeshere,
        itr)

rdd.foreachPartition(sendRecords)

一个可选的潜在改进,如果您可能有大量的分区与执行程序的数量相比,则coalesce您的数据下降为具有与执行程序相同的分区数,从而减少了连接的数量最终制作。

如果我们在JVM中,我们也可以尝试在worker上使用单例模式,但是python执行器在Spark中的工作原理会有些复杂。