文章目录
如果你经常写MapReduce作业,你肯定看到过以下的异常信息:
Application application_1409135750325_48141 failed 2 times due to AM Container for appattempt_1409135750325_48141_000002 exited with exitCode: 143 due to: Container [pid=4733,containerID=container_1409135750325_48141_02_000001] is running beyond physical memory limits. Current usage: 2.0 GB of 2 GB physical memory used; 6.0 GB of 4.2 GB virtual memory used. Killing container.
上面的异常信息已经说的非常详细了,你的作业运行的时候超过了它的内存限制,我们该如何解决这个问题呢?
确保你的作业必须缓存数据
在我们介绍如何修改配置之前,我们先来想想我们的作业是做什么的。通常情况,你的Map或者Reduce task运行时出现内存不足通常意味着你可能把数据缓存在Map或者Reduce task中。数据需要缓存的原因有很多,比如:
1、你的作业将以Parquet格式输出结果数据,Parquet在将数据写入磁盘之前会在内存中缓冲数据;
2、你的代码正在缓存数据。比如你正在将两个数据集join在一起,其中一个数据集在Join之前先缓存数据到内存。
因此,我建议你第一步想想你是否真的需要缓存数据,如果不需要的话减少内存的使用。
YARN是如何监控Container的内存使用
本章节并不是专门介绍MapReduce的,而是介绍YARN一般是如何监控运行容器所占用的内存(在MapReduce情况下,一个container既可以是map也可以是Reduce进程)。
YARN集群的每个slave节点都运行了名为NodeManager的守护进程,而NodeManager进程的一个职责就是监控运行在那个几点上的YARN containers,其中就包括了监控每个容器的内存使用。
为了实现这个,NodeManager定期(默认情况下每隔3s,可以通过修改yarn.nodemanager.container-monitor.interval-ms
)循环遍历所有当前正在运行的容器,计算进程树(process tree,也就是每个容器所有的子进程),对于每个进程检查 /proc/<pid>/stat
文件,(其中,PID就是容器的进程ID),抽取出物理内存(又叫做RSS)和虚拟内存(又叫做VSZ 或者 VSIZE)。
如果虚拟检查被打开(默认情况下为true,可以通过 yarn.nodemanager.vmem-check-enabled
修改),然后YARN将把抽取出来的容器及其子进程的VSIZE加起来和容器最大允许使用的虚拟内存进行比较。最大允许使用的虚拟内存是容器最大可使用的物理内存乘以 yarn.nodemanager.vmem-pmem-ratio
(默认值是2.1)。所以,如果你的YARN容器配置的最大可使用物理内存为2GB,然后我们乘以 2.1 得到的就是容器最大可用的虚拟内存 4.2G。
如果物理内存检查被打开(默认情况为true,可以通过 yarn.nodemanager.pmem-check-enabled
修改),然后YARN将把抽取出来的容器及其子进程的RSS加起来和容器最大允许使用的物理内存进行比较。
如果物理内存或者虚拟内存其中一个的使用大于最大允许使用的,YARN将会被这个容器杀掉,这就是你在本文开头看到的异常信息。
增加MapReduce作业可使用的内存
对于MapReduce作业来说,主要有以下两种配置方式来设置作业运行的内存,而且这两种方式需要一起设置:
1、设置Map和Reduce进程的物理内存;
2、设置Map和Reduce进程的JVM堆大小。
设置Map和Reduce进程的物理内存
我们可以通过在配置文件里面为map 和 reduce容器分别设置 mapreduce.map.memory.mb
和 mapreduce.reduce.memory.mb
参数来限制物理内存的大小。比如如果你想在集群中默认将Map进程的内存限制为2GB,而Reduce进程的内存限制为4GB,那么你可以在 mapred-site.xml
文件里面添加如下配置:
<property> <name>mapreduce.map.memory.mb</name> <value>2048</value> </property> <property> <name>mapreduce.reduce.memory.mb</name> <value>4096</value> </property>
需要注意的是,为作业配置的物理内存必须落在集群中容器允许的最小和最大内存范围中,具体可以分别查看 yarn.scheduler.maximum-allocation-mb
和 yarn.scheduler.minimum-allocation-mb
两个参数。
设置Map和Reduce进程的JVM堆大小
接下来你需要为你的 map 和 reduce 进程设置JVM堆大小。JVM堆大小需要小于进程的物理内存大小;根据经验,我们一般把它设置成物理内存的80%。
可以通过 mapreduce.map.java.opts
和 mapreduce.reduce.java.opts
参数来分别设置 Map 和 Reduce 进程的JVM堆大小。比如我们上面已经将 Map 和 Reduce 的物理内存分别设置为 2GB 和 4GB 了;所以我们可以在 mapred-site.xml
文件中分别设置 Map 和 Reduce 进程的JVM堆大小,如下所示:
<property> <name>mapreduce.map.java.opts</name> <value>-Xmx1638m</value> </property> <property> <name>mapreduce.reduce.java.opts</name> <value>-Xmx3278m</value> </property>
当然,我们还可以在运行作业的时候设置上面那几个参数,来覆盖集群的默认配置,具体的我这就不介绍了。
本博客文章除特别声明,全部都是原创!原创文章版权归过往记忆大数据(过往记忆)所有,未经许可不得转载。
本文链接: 【如何给运行在YARN上的MapReduce作业配置内存】(https://www.iteblog.com/archives/1945.html)
flink on yarn 也出现这种问题了,请问老板怎么解决,