Hadoop作业JVM堆大小设置优化
2014-04-14 11:22
225 查看
作者:过往记忆 | 新浪微博:左手牵右手TEL | 可以转载,
但必须以超链接形式标明文章原始出处和作者信息及版权声明
博客地址:http://www.iteblog.com/
文章标题:《Hadoop作业JVM堆大小设置优化》
本文链接:http://www.iteblog.com/archives/981
Hadoop、Hive、Hbase、Flume等QQ交流群:138615359
前段时间,公司Hadoop集群整体的负载很高,查了一下原因,发现原来是客户端那边在每一个作业上擅自配置了很大的堆空间,从而导致集群负载很高。下面我就来讲讲怎么来现在客户端那边的JVM堆大小的设置。
我们知道,在mapred-site.xml配置文件里面有个mapred.child.java.opts配置,专门来配置一些诸如堆、垃圾回收之类的。看下下面的配置:
默认情况下,-Xmx都是配置200m的,但是在实际情况下,这个显然是不够用的,所以导致客户端那边会设置更大的值。那怎么来限制用户随便设置Xmx的值呢?有下面两种方法:
上面的mapred.task.java.opts属性是我们自己定义的,可以公布给用户配置;然后在mapred.child.java.opts中获取到mapred.task.java.opts的值,同时mapred.child.java.opts属性的final被设置为true,也就是不让客户修改。所以用户对mapred.child.java.opts直接配置是无效的;而且这里我们在获取${mapred.task.java.opts}之后再添加了-Xmx1000m,而在Java中,如果相同的jvm arg写在一起,比如”-Xmx2000m
-Xmx1000m”,后面的会覆盖前面的,也就是说最终“-Xmx1000m”才会生效,通过这种方式,我们就可以有限度的控制客户端那边的heap size了。同样的道理,其他想覆盖的参数我们也可以写到后面。
我们可以通过
来分别配置作业的Map和Reduce阶段的heap的大小。
上述限制客户端那边随便设置堆大小是通过重新定义一个变量给用户使用,这样用户得使用新的变量来定义一些JVM相关的设定,如果用户那边的脚本非常多,他们就需要一个一个脚本的修改mapred.child.java.opts为mapred.task.java.opts。这样会恨不方便。这里介绍另外一种方法。可以通过mapreduce.admin.map.child.java.opts和mapreduce.admin.reduce.child.java.opts来限定作业map和reduce的堆的大小。他们都是管理员设定的map/reduce阶段申请的container的默认JVM启动参数。启动container的命令行会先连接管理员设定参数,然后再连接用户设定参数。我们来看看Hadoop源码是怎么获取客户端和管理员JVM参数的获取的:
通过上面的代码,我们可以发现Hadoop是先获取管理员的JVM参数配置,然后连接客户端那边JVM参数的配置。这样如果管理员那边的配置在客户端那边也配置了,那么客户端这边的配置将会覆盖掉管理员那边的参数配置。所以我们可以修改源码,将
return adminClasspath + ” ” + userClasspath;修改为 return userClasspath + ” ” + adminClasspath;然后在mapred-site.xml文件做如下配置:
这样,我们就可以覆盖客户端那边的配置。
上面两种方法虽然能在一定程度上限制客户端使用堆的大小,但是这样的解决办法不是很好的!因为我们设定所有作业的堆大小都是1000M,但是实际情况下,很多作业不一定都用得到1000M;而且在一些情况下,有些作业用到的heap可能大于1000M,这样会使这样的作业出现OOM的问题。
但必须以超链接形式标明文章原始出处和作者信息及版权声明
博客地址:http://www.iteblog.com/
文章标题:《Hadoop作业JVM堆大小设置优化》
本文链接:http://www.iteblog.com/archives/981
Hadoop、Hive、Hbase、Flume等QQ交流群:138615359
前段时间,公司Hadoop集群整体的负载很高,查了一下原因,发现原来是客户端那边在每一个作业上擅自配置了很大的堆空间,从而导致集群负载很高。下面我就来讲讲怎么来现在客户端那边的JVM堆大小的设置。
我们知道,在mapred-site.xml配置文件里面有个mapred.child.java.opts配置,专门来配置一些诸如堆、垃圾回收之类的。看下下面的配置:
01 | <property> |
02 | <name>mapred.child.java.opts</name> |
03 | <value>-Xmx200m</value> |
04 | <description>Java opts for the task tracker child processes. |
05 | The following symbol, if present, will be interpolated: @taskid @ is |
06 | replaced by current TaskID. Any other occurrences of '@' will go unchanged. |
07 | For example, to enable verbose gc logging to a file named for the taskid in |
08 | /tmp and to set the heap maximum to be a gigabyte, pass a 'value' of: |
09 | -Xmx1024m -verbose:gc -Xloggc:/tmp/ @taskid @.gc |
10 |
11 | The configuration variable mapred.child.ulimit can be used to control the |
12 | maximum virtual memory of the child processes. |
13 | </description> |
14 | </property> |
一、可以自己定义一个变量,比如如下:
01 | <property> |
02 | <name>mapred.task.java.opts</name> |
03 | <value>-Xmx2000m</value> |
04 | </property> |
05 |
06 | <property> |
07 | <name>mapred.child.java.opts</name> |
08 | <value>${mapred.task.java.opts} -Xmx1000m</value> |
09 | < final > true </ final > |
10 | </property> |
-Xmx1000m”,后面的会覆盖前面的,也就是说最终“-Xmx1000m”才会生效,通过这种方式,我们就可以有限度的控制客户端那边的heap size了。同样的道理,其他想覆盖的参数我们也可以写到后面。
我们可以通过
01 | <property> |
02 | <name>mapred.map.child.java.opts</name> |
03 | <value> |
04 | -Xmx512M |
05 | </value> |
06 | </property> |
07 |
08 | <property> |
09 | <name>mapred.reduce.child.java.opts</name> |
10 | <value> |
11 | -Xmx1024M |
12 | </value> |
13 | </property> |
二、通过mapreduce.admin.map.child.java.opts和和mapreduce.admin.reduce.child.java.opts设定
上述限制客户端那边随便设置堆大小是通过重新定义一个变量给用户使用,这样用户得使用新的变量来定义一些JVM相关的设定,如果用户那边的脚本非常多,他们就需要一个一个脚本的修改mapred.child.java.opts为mapred.task.java.opts。这样会恨不方便。这里介绍另外一种方法。可以通过mapreduce.admin.map.child.java.opts和mapreduce.admin.reduce.child.java.opts来限定作业map和reduce的堆的大小。他们都是管理员设定的map/reduce阶段申请的container的默认JVM启动参数。启动container的命令行会先连接管理员设定参数,然后再连接用户设定参数。我们来看看Hadoop源码是怎么获取客户端和管理员JVM参数的获取的:01 | private static String getChildJavaOpts(JobConf jobConf, boolean isMapTask) { |
02 | String userClasspath = "" ; |
03 | String adminClasspath = "" ; |
04 | if (isMapTask) { |
05 | userClasspath = |
06 | jobConf.get( |
07 | JobConf.MAPRED_MAP_TASK_JAVA_OPTS, |
08 | jobConf.get( |
09 | JobConf.MAPRED_TASK_JAVA_OPTS, |
10 | JobConf.DEFAULT_MAPRED_TASK_JAVA_OPTS) |
11 | ); |
12 | adminClasspath = |
13 | jobConf.get( |
14 | MRJobConfig.MAPRED_MAP_ADMIN_JAVA_OPTS, |
15 | MRJobConfig.DEFAULT_MAPRED_ADMIN_JAVA_OPTS); |
16 | } else { |
17 | userClasspath = |
18 | jobConf.get( |
19 | JobConf.MAPRED_REDUCE_TASK_JAVA_OPTS, |
20 | jobConf.get( |
21 | JobConf.MAPRED_TASK_JAVA_OPTS, |
22 | JobConf.DEFAULT_MAPRED_TASK_JAVA_OPTS) |
23 | ); |
24 | adminClasspath = |
25 | jobConf.get( |
26 | MRJobConfig.MAPRED_REDUCE_ADMIN_JAVA_OPTS, |
27 | MRJobConfig.DEFAULT_MAPRED_ADMIN_JAVA_OPTS); |
28 | } |
29 |
30 | // Add admin classpath first so it can be overridden by user. |
31 | return adminClasspath + " " + userClasspath; |
32 | } |
return adminClasspath + ” ” + userClasspath;修改为 return userClasspath + ” ” + adminClasspath;然后在mapred-site.xml文件做如下配置:
1 | <property> |
2 | <name>mapreduce.admin.map.child.java.opts</name> |
3 | <value>-Xmx1000m</value> |
4 | </property> |
5 | <property> |
6 | <name>mapreduce.admin.reduce.child.java.opts</name> |
7 | <value>-Xmx1000m</value> |
8 | </property> |
总结
上面两种方法虽然能在一定程度上限制客户端使用堆的大小,但是这样的解决办法不是很好的!因为我们设定所有作业的堆大小都是1000M,但是实际情况下,很多作业不一定都用得到1000M;而且在一些情况下,有些作业用到的heap可能大于1000M,这样会使这样的作业出现OOM的问题。
相关文章推荐
- Hadoop作业JVM堆大小设置优化
- Hadoop作业JVM堆大小设置优化 [转]
- Hadoop作业JVM堆优化汇总及JVM复用
- 根据应用程序设置JVM参数(二)-优化新生代大小
- hadoop hdfs 命令行 设置文件夹大小的上限 quota:配额
- ADT开发中的一些优化设置:代码背景色、代码字体大小、代码自动补全
- hadoop2.x作业提交时conf设置
- Hadoop平台作业参数设置关于mapreduce.job.split.metainfo.maxsize的说明
- jvm优化(二)JVM 内存大小设置
- Hadoop 文件块大小设置
- 源码推荐(7.15):重写UIFont方法 设置字体格式以及大小,可重用的水平滚动scrollView列表 极致性能优化
- Hadoop作业优化
- Hadoop Map&Reduce个数优化设置以及JVM重用
- Elasticsearch中设置JVM堆的大小(翻译)
- 根据应用程序设置JVM参数(三)-优化老年代大小
- [置顶] Hadoop作业运行(OOM)内存溢出错误分类和参数调优化
- 在hadoop中如何进入本地调试、及如何设置split的大小
- hadoop作业调优参数整理及原理(整个mapreduce运行流程都讲的清楚,一步一步优化)
- hadoop优化:文件系统设置noatime
- Map/Reduce Task JVM 堆大小设置优化