在我的Spark Streaming(Spark 2.1.0)应用程序中,我需要从文件构建图形并初始化该图形需要5到10秒。
所以我尝试每个执行器初始化一次,因此它只会被初始化一次。
运行应用程序后,我注意到每个执行程序启动的次数不止一次,每次都有不同的进程ID(每个进程都有自己的记录器)。
是不是每个执行者都拥有自己的JVM并且它自己的进程?或者只有当我使用像Scala / Java这样的JVM语言开发时才有用? PySpark中的执行程序是否为新任务生成新进程?
如果他们这样做,我怎样才能确保我的图表对象真的只会被启动一次?
我初始化对象的方式:
class MySingletons(object):
kafka_producer = KafkaProducer(bootstrap_servers=['localhost:9092'])
tagger = _init_tagger() # This returns an object with a graph inside of it
@classmethod
def handle_batch(cls, records_batch):
analyzed = cls.tagger.tag(records_batch)
return analyzed
然后我在驱动程序中调用它:
def handle_partition(records: Sequence):
records_lst = list(records)
if len(records_lst) > 0:
MySingletons.handle_batch(records_lst)
def handle_rdd(rdd: RDD):
rdd_values = rdd.map(lambda x: x[1])
rdd_values.foreachPartition(handle_partition)
ssc.union(*streams).filter(lambda x: x[1] is not None).foreachRDD(handle_rdd)
ssc.start()
ssc.awaitTermination()
谢谢:)
答案 0 :(得分:2)
简而言之,JVM语言和Python之间存在显着差异:
Python对象的生命周期将限于特定的子进程,每个进程都有自己的"单例"。
此外,如果spark.python.worker.reuse
false
,或者如果长时间闲置,则可以杀死Python工作人员。
最后,动态分配会使事情进一步复杂化。
根据逻辑的细节,有很多可能的解决方法,但通常涉及非常普遍。