【问题标题】:Spark cluster OutOfMemoryError with way more memory then neededSpark 集群 OutOfMemoryError 需要更多内存
【发布时间】:2018-06-18 14:47:42
【问题描述】:

我有一个带有 28gb 驱动程序和 8 个 56gb 工作程序的 spark 集群。我正在尝试处理 4gb 文件。我可以在我自己的笔记本电脑上的 16gb 内存上不使用 spark 成功处理此文件,因此没有内存泄漏导致使用完整的 56gb,它也可以处理较小的示例文件就好了。我正在使用 azure databricks 提交这份工作(尽管这应该无关紧要)。我的 spark 集群上的所有配置都是默认的。

有问题的代码

  var ou = distData.map(s => ProcessObj.exec(s.toString) ).collect

完整的堆栈跟踪:

java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3236)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
at org.apache.spark.util.ByteBufferOutputStream.write(ByteBufferOutputStream.scala:41)
at java.io.DataOutputStream.write(DataOutputStream.java:107)
at java.io.ObjectOutputStream$BlockDataOutputStream.write(ObjectOutputStream.java:1853)
at java.io.ObjectOutputStream.write(ObjectOutputStream.java:709)
at java.nio.channels.Channels$WritableByteChannelImpl.write(Channels.java:458)
at org.apache.spark.util.SerializableBuffer$$anonfun$writeObject$1.apply(SerializableBuffer.scala:49)
at org.apache.spark.util.SerializableBuffer$$anonfun$writeObject$1.apply(SerializableBuffer.scala:47)
at org.apache.spark.util.Utils$.tryOrIOException(Utils.scala:1359)
at org.apache.spark.util.SerializableBuffer.writeObject(SerializableBuffer.scala:47)
at sun.reflect.GeneratedMethodAccessor153.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1128)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:43)
at org.apache.spark.rpc.netty.RequestMessage.serialize(NettyRpcEnv.scala:565)
at org.apache.spark.rpc.netty.NettyRpcEnv.send(NettyRpcEnv.scala:193)
at org.apache.spark.rpc.netty.NettyRpcEndpointRef.send(NettyRpcEnv.scala:528)
at org.apache.spark.scheduler.cluster.CoarseGrainedSchedulerBackend$DriverEndpoint$$anonfun$launchTasks$1.apply(CoarseGrainedSchedulerBackend.scala:315)
at org.apache.spark.scheduler.cluster.CoarseGrainedSchedulerBackend$DriverEndpoint$$anonfun$launchTasks$1.apply(CoarseGrainedSchedulerBackend.scala:293)
at scala.collection.Iterator$class.foreach(Iterator.scala:893)

更新:

尝试使用以下 spark 配置,但仍然出现内存不足错误:

spark.executor.memory 40g
spark.driver.memory 20g

【问题讨论】:

    标签: azure apache-spark databricks


    【解决方案1】:

    spark.driver.memory 默认为 1GB。 Azure 上预配置的 Spark 可能会有所不同,但它似乎仍然少于您尝试处理的数据量。

    然后你在DataFrame上调用collect(),结果内容将被传输到驱动主机,所以它应该能够存储在驱动进程的内存中,这是一个具有预设可用内存量的JVM进程(一般无法将其大小调整为所有主机内存)。

    【讨论】:

    • 谢谢@gemelen。我将spark.executor.memory 40gspark.driver.memory 20g 配置添加到集群中,以防万一,重新启动并再次运行该作业,但仍然出现相同的错误。还有其他想法吗?
    • 有两个方向: 1.按照建议使用Spark - 以分布式方式处理您的文件并将结果存储在分布式存储(HDFS或对象存储)上,因此没有数据会命中驱动程序. 2. 调查您真正需要多少内存 - 您可以从观察 Spark 应用程序 UI 的存储页面上的内存指标开始(或使用其他分析工具,如用于 JVM 分析的工具)。
    • 好的,我会研究 1,因为这正是我想要做的。该函数处理单行并将新行输出到 hdfs 上的文件中。但是,目前我正在收集输出,然后在脚本的后面部分写入 hdfs 中的输出文件,因为我不知道如何在集群上执行此操作。到时候我会更多地研究这种方法,谢谢!
    • @jayjay93 很高兴你能接受满意的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多