我希望在我的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()
我应该在哪里定义我的连接池,只有一个由执行者?
答案 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中的工作原理会有些复杂。