我在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)
答案 0 :(得分:1)
如果您正在使用KafkaUtil.createStream(....),则单个Receiver将在spark执行器中运行,如果主题被分配,则为每个分区运行多个接收器线程。因此,如果您的流有大字符串对象且频率很高且所有线程共享单个执行程序内存,则可能会出现OOM问题。
以下是可能的解决方案。
由于作业在接收器中内存不足,首先检查批处理和块间隔属性。如果批次间隔更重(如5分钟),请尝试使用较小的值,如(100毫秒)。
将每秒收到的记录的速率限制为“spark.streaming.receiver.maxRate”,同时确保 “spark.streaming.unpersist”值为“true”。