由于java.lang.OutOfMemoryError,为什么Spark Streaming在String解码时失败?

时间:2016-11-23 12:19:44

标签: apache-spark apache-kafka spark-streaming

我在3个节点的YARN集群上运行Spark Streaming(createStream API)应用程序,每个节点有128G RAM(!)应用程序从Kafka主题读取记录并写入HDFS。

大多数情况下,无论我为执行程序/驱动程序配置了多少内存,应用程序都会因为Java堆错误而导致失败/被杀死(主要是接收器失败)。

16/11/23 13:00:20 WARN ReceiverTracker: Error reported by receiver for stream 0: Error handling message; exiting - java.lang.OutOfMemoryError: Java heap space
        at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:149)
        at java.lang.StringCoding.decode(StringCoding.java:193)
        at java.lang.String.<init>(String.java:426)
        at java.lang.String.<init>(String.java:491)
        at kafka.serializer.StringDecoder.fromBytes(Decoder.scala:50)
        at kafka.serializer.StringDecoder.fromBytes(Decoder.scala:42)
        at kafka.message.MessageAndMetadata.message(MessageAndMetadata.scala:32)
        at org.apache.spark.streaming.kafka.KafkaReceiver$MessageHandler.run(KafkaInputDStream.scala:137)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

1 个答案:

答案 0 :(得分:1)

如果您正在使用KafkaUtil.createStream(....),则单个Receiver将在spark执行器中运行,如果主题被分配,则为每个分区运行多个接收器线程。因此,如果您的流有大字符串对象且频率很高且所有线程共享单个执行程序内存,则可能会出现OOM问题。

以下是可能的解决方案。

  1. 由于作业在接收器中内存不足,首先检查批处理和块间隔属性。如果批次间隔更重(如5分钟),请尝试使用较小的值,如(100毫秒)。

  2. 将每秒收到的记录的速率限制为“spark.streaming.receiver.maxRate”,同时确保 “spark.streaming.unpersist”值为“true”。

  3. 您可以使用KafkaUtil.KafkaUtils.createDirectStream [String,String, StringDecoder,StringDecoder](streamingContext,kafkaParams, 话题)。在这种情况下,而不是单个接收器火花执行器 直接连接到kafka分区引线并接收数据 parallel(每个kfka分区是一个KafkaRDD分区)。不像 单个接收器执行器中的多个线程在这里多个 执行程序将并行运行,并将分配负载。