pyspark流式传输:无法在worker上执行rdd.count()

时间:2018-07-12 09:09:34

标签: apache-spark pyspark spark-streaming

我有一个pyspark流作业,其工作大致如下:

def printrddcount(rdd):
    c = rdd.count()
    print("{1}: Received an RDD of {0} rows".format("CANNOTCOUNT", datetime.now().isoformat()) )

然后:

...
stream.foreachRDD(printrddcount)

从我得到的结果中,将在worker中执行printrdd函数 而且,是的,我知道在工作程序中执行print()是个坏主意。但这不是重点。 我很确定,直到最近,这段代码才能正常工作。 (而且,它看起来也有所不同,因为'c'的内容实际上是在print语句中打印的,而不是仅仅被收集,然后被丢弃...)

但是现在看来(突然之间?),然后rdd.count()停止工作了,这使我的工作进程死了,说:

UnpicklingError: NEWOBJ class argument has NULL tp_new

完整(仅适用于python)stacktrace:

Caused by: org.apache.spark.api.python.PythonException: Traceback (most recent call last):
  File "/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/worker.py", line 163, in main
    func, profiler, deserializer, serializer = read_command(pickleSer, infile)
  File "/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/worker.py", line 54, in read_command
command = serializer._read_with_length(file)
  File "/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/serializers.py", line 169, in _read_with_length
    return self.loads(obj)
  File "/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/serializers.py", line 454, in loads
    return pickle.loads(obj)
UnpicklingError: NEWOBJ class argument has NULL tp_new

失败的那一行确实是rdd.count()

有人知道rdd.count()为什么会失败吗? 如果应该序列化某些内容,则应该是rdd,对吧?

1 个答案:

答案 0 :(得分:0)

好的。我进一步调查了。 rdd.count()没问题

唯一的错误是,rdd在管道上存在另一种以某种方式“损坏”(关闭?无效?沿着这些方向的东西)的转换。 因此,当使用printrddcount函数时,它无法再进行序列化并给出错误。

问题出在如下代码中:

...
log = logging.getLogger(__name__)
...
def parse(parse_function):
    def parse_function_wrapper(event):
        try:
            log.info("parsing")
            new_event = parse_function(event)
    except ParsingFailedException as e:
        pass
    return new_event
return parse_function_wrapper

然后:

stream = stream.map(parse(parse_event))

现在,log.info(尝试了很多变体,开始时是在异常处理程序中进行记录)才是造成问题的原因。 这使我说,很可能是由于某种原因而无法序列化的记录器对象。

我自己关闭了该线程,因为它实际上与rdd序列化无关;甚至甚至没有使用pyspark。