今天写了一个简单的MapReduce程序,结果一跑就卡在mapreduce.Job: Running job这里,记录一下解决问题的过程,我在一台内存8G的笔记本上用虚拟机搭建集群,三个虚拟机都开了1G内存,Hadoop版本是3.0.3
打开对应的url检查job情况(即上图倒数第二行的http://master/cluster/app/application_1531899388083_0001),任务状态一直在ACCEPTED:waiting for AM container to be allocated,launched and register with RM,似乎是空间分配的问题
回到master:8088/cluster/cluster,发现两个slave节点都是unhealthy
果然是磁盘空间不足,因为我是自己学习搭的虚拟机集群,懒得扩容,按照StackOverflow上的这个帖子(https://stackoverflow.com/questions/29131449/why-does-hadoop-report-unhealthy-node-local-dirs-and-log-dirs-are-bad),简单粗暴地修改了配置,把健康检查上限提高到98.5%,让他不要轻易狗带,之后重新检查集群状态,Active Nodes变成2
<property>
<name>yarn.nodemanager.disk-health-checker.max-disk-utilization-per-disk-percentage</name>
<value>98.5</value>
</property>
重新启动集群,重新运行MapReduce程序,继续报错2.5GB of 2.1GB virtual memory used. Killing container.
可以看到这个MapReduce程序居然申请了2.5G的虚拟内存,超过了默认的虚拟内存2.1G的上限,这里我找到了两种解决办法
1、修改虚拟内存上限
在yarn-site.xml文件里,添加如下设置,因为默认申请的内存大小是1G,这里设置的是虚拟内存和物理内存比值,原来是2.1,现在改成4.1,就可以运行了
<property>
<name>yarn.nodemanager.vmem-pmem-ratio</name>
<value>4.1</value>
</property>
从运行结果上来看,占用了内存资源非常巨大,我运行的只是一个小程序,处理的输入文件只有6行,一个简单的程序用了如此大的内存,大约2.5G,我感到很不优雅
2、修改mapred-site.xml内存大小配置
参考了博文中的各种内存配置优化,把MapReduce运行过程中的内存限制得非常小
上面的图可以看出,MapReduce一共申请了3.5G的内存,其中1G是物理内存,2.5G是虚拟内存,大致符合内存2.1的比值,查看官网的属性,可以发现三个和内存大小有关的属性https://hadoop.apache.org/docs/r2.7.2/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml
(1)mapreduce.map.memory.mb 默认1G,map执行时分配的内存
(2)mapreduce.reduce.memory.mb 默认1G,reduce执行时分配的内存
(3)yarn.app.mapreduce.am.resource.mb 默认1.5G, MR AppMaster分配的内存
这三个内存加起来就是3.5G,不负责任地推测应该就是MapReduce中的内存主要组成部分,其中(1)(2)项要在客户端修改,(3)我还未修改成功
对客户端mapred-site.xml修改如下(不是集群,这很重要,我用Windows下的Idea开发,所以在Windows上的mapred-site.xml修改),在服务器修改不起作用,除了memory.mb这个Task总内存要改之外,java.opts这个堆大小也要修改,我看官网的默认值两个比例大概是1.5。mapreduce.task.io.sort.mb这个值设置用于 map 端排序的缓冲区大小,是占用Java堆大小的,一开始没有加上这个配置,默认值大于我设置的堆大小,不停报Java Heap Space错误。其实很多博客都说建议reduce的大小要是map的两倍,我这个只是练习,没有研究得那么透彻。
<property>
<name>mapreduce.map.memory.mb</name>
<value>48</value>
</property>
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx32M</value>
</property>
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>48</value>
</property>
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xmx32M</value>
</property>
<property>
<name>mapreduce.task.io.sort.mb</name>
<value>4</value>
</property>
修改后可以运行了,结果用了约1.8G