我在Google Cloud Dataproc上使用Spark流来执行一个框架(用Python编写),该框架由几个连续的管道组成,每个管道代表Dataproc上的一个作业,它基本上从Kafka队列中读取并将转换后的输出写入Bigtable。所有管道组合每天通过2个集群处理几千兆字节的数据,一个有3个工作节点,另一个有4个。
在Dataproc之上运行这个Spark流式传输框架已经相当稳定,直到5月初(准确地说是5月3日):我们开始遇到频繁的套接字超时异常,这会终止我们的管道。它似乎与集群上的负载无关,因为它没有显着增加。它也在一天中非常随机地发生,我检查了可能相关的代码更改,但我找不到任何。此外,这似乎只发生在具有4个工作节点的集群上,而具有3个节点的集群上的管道非常相似,并且根本不会遇到超时。我已经重新创建了两次集群,但问题仍然存在,它会影响在此数据集群上运行的所有管道。具有3个节点的群集是n1-standard-4
机器类型,而具有4个节点的麻烦群集是n1-standard-8
机器类型,除此之外,它们的配置相同。
发生问题并且作业终止时执行管道作业的示例输出:
java.net.SocketTimeoutException: Accept timed out
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at org.apache.spark.api.python.PythonRDD$$anon$2.run(PythonRDD.scala:645)
16/05/23 14:45:45 ERROR org.apache.spark.streaming.scheduler.JobScheduler: Error running job streaming job 1464014740000 ms.0
org.apache.spark.SparkException: An exception was raised by Python:
Traceback (most recent call last):
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/streaming/util.py", line 65, in call
r = self.func(t, *rdds)
File "/tmp/b85990ba-e152-4d5b-8977-fb38915e78c4/transformfwpythonfiles.zip/transformationsframework/StreamManager.py", line 138, in process_kafka_rdd
.foreach(lambda *args: None)
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/rdd.py", line 747, in foreach
self.mapPartitions(processPartition).count() # Force evaluation
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/rdd.py", line 1004, in count
return self.mapPartitions(lambda i: [sum(1 for _ in i)]).sum()
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/rdd.py", line 995, in sum
return self.mapPartitions(lambda x: [sum(x)]).fold(0, operator.add)
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/rdd.py", line 869, in fold
vals = self.mapPartitions(func).collect()
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/rdd.py", line 772, in collect
return list(_load_from_socket(port, self._jrdd_deserializer))
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/rdd.py", line 142, in _load_from_socket
for item in serializer.load_stream(rf):
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/serializers.py", line 139, in load_stream
yield self._read_with_length(stream)
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/serializers.py", line 156, in _read_with_length
length = read_int(stream)
File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/serializers.py", line 543, in read_int
length = stream.read(4)
File "/usr/lib/python2.7/socket.py", line 380, in read
data = self._sock.recv(left)
timeout: timed out
stacktrace的开始在我们的StreamManager
模块中,方法process_kafka_rdd:它在Kafka消息的直接流中处理单个离散RDD。我们将Kafka与Spark流媒体的集成基于"直接方法"在http://spark.apache.org/docs/latest/streaming-kafka-integration.html
答案 0 :(得分:1)
我对Spark和套接字错误的体验是,有些执行者突然死亡。当时与其进行通信的其他一些执行程序会引发套接字错误。
根据我的经验,意外遗嘱执行死亡的原因是资源匮乏,通常是记忆力不足。
(调整执行程序可以使用的内存量非常重要。默认值通常太低。但我怀疑你已经意识到了这一点。)
我认为Spark在纱线上运行?不幸的是,根据我的经验,Spark在纱线内部发生问题时报告问题的原因很糟糕。不幸的是,人们不得不深入研究纱线日志,以找出实际导致突然执行死亡的原因。执行者每人都在纱线“容器”中运行;在纱线原木的某处,应该有一个容器掉落的记录。