在YARN中,Spark应用程序的物理内存需求不断增加

6

我在YARN中运行一个Spark应用程序,有两个执行器,Xms / Xmx为32 GB,spark.yarn.excutor.memoryOverhead为6 GB。

我发现该应用程序的物理内存不断增加,并最终被节点管理器杀死:

2015-07-25 15:07:05,354 WARN org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl: Container [pid=10508,containerID=container_1437828324746_0002_01_000003] is running beyond physical memory limits. Current usage: 38.0 GB of 38 GB physical memory used; 39.5 GB of 152 GB virtual memory used. Killing container.
Dump of the process-tree for container_1437828324746_0002_01_000003 :
    |- PID PPID PGRPID SESSID CMD_NAME USER_MODE_TIME(MILLIS) SYSTEM_TIME(MILLIS) VMEM_USAGE(BYTES) RSSMEM_USAGE(PAGES) FULL_CMD_LINE
    |- 10508 9563 10508 10508 (bash) 0 0 9433088 314 /bin/bash -c /usr/java/default/bin/java -server -XX:OnOutOfMemoryError='kill %p' -Xms32768m -Xmx32768m  -Dlog4j.configuration=log4j-executor.properties -XX:MetaspaceSize=512m -XX:+UseG1GC -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:gc.log -XX:AdaptiveSizePolicyOutputInterval=1  -XX:+UseGCLogFileRotation -XX:GCLogFileSize=500M -XX:NumberOfGCLogFiles=1 -XX:MaxDirectMemorySize=3500M -XX:NewRatio=3 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=36082 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -XX:NativeMemoryTracking=detail -XX:ReservedCodeCacheSize=100M -XX:MaxMetaspaceSize=512m -XX:CompressedClassSpaceSize=256m -Djava.io.tmpdir=/data/yarn/datanode/nm-local-dir/usercache/admin/appcache/application_1437828324746_0002/container_1437828324746_0002_01_000003/tmp '-Dspark.driver.port=43354' -Dspark.yarn.app.container.log.dir=/opt/hadoop/logs/userlogs/application_1437828324746_0002/container_1437828324746_0002_01_000003 org.apache.spark.executor.CoarseGrainedExecutorBackend akka.tcp://sparkDriver@nn1:43354/user/CoarseGrainedScheduler 1 dn3 6 application_1437828324746_0002 1> /opt/hadoop/logs/userlogs/application_1437828324746_0002/container_1437828324746_0002_01_000003/stdout 2> /opt/hadoop/logs/userlogs/application_1437828324746_0002/container_1437828324746_0002_01_000003/stderr

我禁用了YARN的参数"yarn.nodemanager.pmem-check-enabled",发现物理内存使用量增加到了40GB。

我检查了/proc/pid/smaps中的总RSS值,它与Yarn报告的物理内存和top命令中看到的值相同。

我检查了堆中没有问题,但是非堆/本地内存中的某些内容正在增加。我使用了诸如Visual VM之类的工具,但没有发现任何正在增加的内容。MaxDirectMmeory也没有超过600MB。活动线程的峰值为70-80个,线程堆栈大小不超过100MB。MetaspaceSize大约为60-70MB。

顺便说一下,我使用的是Spark 1.2和Hadoop 2.4.0,我的Spark应用程序基于Spark SQL,是一个HDFS读写密集型应用程序,并在Spark SQL的内存缓存中缓存数据。

我应该在哪里查找内存泄漏的问题,或者是否已经有工具可以解决这个问题?

1个回答

4

最终我成功解决了这个问题。问题在于Spark SQL的parquet写入路径中创建的压缩器没有被回收,因此我的执行者为每个parquet写入文件创建一个全新的压缩器(从本地内存中),从而耗尽了物理内存限制。

我在Parquet Jira上开了以下的bug,并提出了相应的PR:

https://issues.apache.org/jira/browse/PARQUET-353

这解决了我的内存问题。
附注:只有在使用Parquet写入密集型应用程序时才会出现此问题。

1
你是怎么发现它是Parquet格式的?我们遇到了类似的问题(但我们没有使用Parquet格式),我们不确定如何找到罪魁祸首。 - DanLebrero
我们曾经遇到过一个类似的(堆外)OOM问题,非常难以追踪。结果发现是Hadoop本地库用于gzip输出(hadoop.native.lib)。现在我们在启动时处理这个问题,虽然性能不如以前好,但泄漏问题已经解决了:JobConf jobConf = new JobConf(sc.hadoopConfiguration()); jobConf.setBoolean("hadoop.native.lib", false); - Jon Chase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接