简而言之::我在AWS的EMR上运行pySpark应用程序。当我使用自定义函数映射rdd时,该函数驻留在外部程序包的外部模块中(以.py文件形式在.zip文件中装运),群集被卡住-运行状态保持不变,直到不再显示日志行为止我手动将其终止。
不是什么: 这不是一个适当的导入异常-因为这会在执行导入行时终止应用程序,并引发相应的异常,但不会发生。另外,如下所示,当被调用函数位于“问题”模块中时,调用与lambda相似的映射函数。
它是什么::仅当程序尝试使用该模块中的函数作为主程序中编写的转换中的映射函数时,才会发生该错误。此外,如果我删除了外部文件(“问题”模块)中突出显示的导入行,那么在此最小的bug复制环境中(但在实际情况下使用该导入)在该文件中从未使用过该导入),该错误将停止存在。
下面是该错误的最小示例的代码,包括注释2条重要的代码以及一些技术信息。任何帮助将不胜感激。
这是主程序:
import spark_context_holder
from reproducing_bugs_external_package import reproducing_bugs_external_file
sc = spark_context_holder.sc
log = spark_context_holder.log
def make_nums_rdd():
return sc.parallelize([1, 2, 3] * 300).map(lambda x: x * x / 1.45)
log.warn("Starting my code!")
sum = sc.parallelize([1,2,3]*300).map(lambda x: x*x/1.45).sum()
log.warn("The calculated sum using in-line expression, which doesn't mean anything more than 'succeeded in carrying out the calculation on the cluster', is {}!".format(sum))
simple_sum_rdd = make_nums_rdd()
log.warn("The calculated sum using the in-file function, which doesn't mean anything more than 'succeeded in carrying out the calculation on the cluster', is {}!".format(simple_sum_rdd.sum()))
simple_sum_rdd = reproducing_bugs_external_file.make_nums_rdd(sc)
log.warn("The calculated sum using the external file's function, which doesn't mean anything more than 'succeeded in carrying out the calculation on the cluster', is {}!".format(simple_sum_rdd.sum()))
simple_sum_rdd = sc.parallelize([1,2,3]*300).map(reproducing_bugs_external_file.calc_func)
log.warn("The calculated sum using the external file's mapping function, which doesn't mean anything more than 'succeeded in carrying out the calculation on the cluster', is {}!".format(simple_sum_rdd.sum()))
# This last line does not get logged, while the others up until this one do. Here the cluster gets stuck on Running status without outputting any more log lines
在作为--py-files交付的zip文件中,我具有以下结构:
> spark_context_holde.py
> reproducing_bugs_external_package
>> __init__.py
>> reproducing_bugs_external_file.py
这是它们各自的内容:
spark_context_holder.py
from pyspark.sql import SparkSession
from pyspark import SparkConf, SparkContext
conf = SparkConf().setAppName("kac_walk_experiment")
sc = SparkContext(conf=conf)
spark = SparkSession(sc)
log4jLogger = sc._jvm.org.apache.log4j
log = log4jLogger.LogManager.getLogger("dbg_et")
# sc.setLogLevel("ALL")
def getParallelismAlternative():
return int(sc.getConf().get('spark.cores.max'))
__ init __。py
from . import reproducing_bugs_external_file
__all__ = [reproducing_bugs_external_file]
reproduction_bugs_external_file.py
import numpy
import spark_context_holder # If this is removed - the bug stops!
def make_nums_rdd(sc):
return sc.parallelize([1, 2, 3] * 300).map(lambda x: x * x / 1.45)
def calc_func(x):
return x*x/1.45
更多技术细节:
答案 0 :(得分:1)
我认为您的根本问题是,您要获取一堆Pyspark设置代码,这些代码仅在主节点上运行,而在从属节点上运行。这些行没有理由:
from pyspark.sql import SparkSession
from pyspark import SparkConf, SparkContext
conf = SparkConf().setAppName("kac_walk_experiment")
sc = SparkContext(conf=conf)
spark = SparkSession(sc)
log4jLogger = sc._jvm.org.apache.log4j
log = log4jLogger.LogManager.getLogger("dbg_et")
首先应该在外部模块中,并且绝对不应该在要通过--py-files
压缩并导出到从属节点的模块中使用。这肯定会导致很多不确定的行为,可能甚至包括您所得到的悬挂错误。
将以上行移动到您的主程序中,一切都会好起来。您还必须重写spark_context_holder.py
中的所有其余代码才能匹配。例如,getParallelismAlternative
将必须以sc
作为参数:
def getParallelismAlternative(sc):
return int(sc.getConf().get('spark.cores.max'))