分享

计算Job运行时的CPU与内存平均利用率(MapReduce)

howtodown 发表于 2014-12-23 22:44:27 [显示全部楼层] 只看大图 回帖奖励 阅读模式 关闭右栏 8 21760


问题导读

1.数据采集什么时候开始与结束?
2.如何获取运行task的JVM pid?







  Hadoop集群上运行有多道MapReduce Job,到底每个Job消费集群计算资源(CPU,内存)的情况如何,通常我们是不知道的。这节来探讨下如果想获得这些信息,应该怎样做。

    每个Job在运行时是散布在TaskTracker上,由不同的JVM来执行。所以这个问题归根结底就是想获取每个运行task的JVM对资源的消费情况。对于这种获取分布式环境数据的例子,就可以采用MapReduce框架自带的Counter机制,由它来采集各JVM运行期的实时数据,然后在Job结束后,做最终分析。

这项任务的意义在哪里?
    正常情况下,Job会因为数据范围、服务的应用、数据量的大小及MapReduce逻辑的复杂程度等因素而被定义为不同的类别。当类别的概念形成后,我们就想知道每个类别Job对集群资源的使用情况是否符合预期,如果可以获得这些数据,就可以根据资源使用情况对Job的执行时间做相应的调整,以避免对其它Job的影响。

数据采集什么时候开始与结束?
    我们的目标是分析每个子JVM的资源消耗情况,就应该在子JVM开始运行时介入收集。站在MapReduce框架外,只有一个地方可以作为介入点:Mapper和Reducer的setup方法。它的参数是task运行期Context,可以很方便地调用Counter。那我们的入口就可以像这样

  1. public class ResourceCollectMapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>
  2.                                                         extends Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
  3.         ChildJVMResourceCollector collector = null;
  4.         public void setup(Context context) {
  5.                 collector = new ChildJVMResourceCollector(context);
  6.                 collector.start();
  7.         }
  8.        
  9. }
复制代码





    资源收集器是一个独立线程,在setup方法中启动,在cleanup方法调用时结束。本来整个task的执行过程就包含在setup与cleanup之间,所以我们完全有机会收集这个过程中的资源利用情况。

如何获取运行task的JVM pid?
    运行task的子JVM是由TaskTracker创建的,对用户完全透明。但幸运的是,TaskTrack在创建这个子JVM时,把它的pid作为参数传给了子JVM。获取的方式如下

  1. private String getChildJVMPid() {
  2.         String pid = "";
  3.         if (!Shell.WINDOWS) {
  4.                 pid = System.getenv().get("JVM_PID");
  5.         }
  6.         return pid;
  7. }
复制代码



怎样根据pid获取系统级的资源使用率?
    得到当前子JVM的进程号后,就能用这个进程号查询Linux系统当前进程的资源使用情况。查询的方式网上很多资料都有说明

7a01b303-084a-36f4-a89a-b59a052daa9e.jpg

    上图是通过ps命令查询某个进程的CPU与内存使用情况的截图。其它相似的查询方式大家可以自行实验
    如果采用上述的linux命令,就需要分开组装,并调用Hadoop提供的Shell组件。
  1. String[] queryCommand = new String[]{"ps", "-o", "%cpu,%mem", pid};
  2. String result = Shell.execCommand(queryCommand);
复制代码





返回的查询结果是一个字符串,解析字符串,拿到想要的结果,以特定的key把结果存入Counter中(当然获取次数也需要收集,在Counter中由独立key标识),这样我们的一次数据获取过程就结束了。

最终怎样分析?
    在Job结束后,根据特定的key获取相应的数据,然后除以获取次数,就是平均的CPU与内存使用率。

要注意的情况是?
    在这个过程中需要注意有两个地方:
    1. 尽量让获取资源的线程不要占用太多的执行时间,每隔一段时间启用一次,减少对正常task执行的影响;
    2. 如果遇到某个Job的多个task共用一个子JVM的情况(MapReduce优化的一点,减少频繁创建/销毁JVM的代价),就需要确保在当前task的cleanup方法中一定让获取资源的线程终结掉。这个线程包含着task运行期的Context,如果是Map task的话,那个默认100MB的内存缓冲区也在其中,可能会有OOM问题而影响下一个task的创建过程。




已有(8)人评论

跳转到指定楼层
lixiaoliang7 发表于 2014-12-24 07:22:28
使用的是HIVE,所以无法使用计数器…
回复

使用道具 举报

355815741 发表于 2014-12-24 08:58:04
非常的东西,学习了,谢谢分享~
回复

使用道具 举报

zzuyao 发表于 2014-12-24 09:59:18
楼主,请教几个问题:
1.你们集群监控用的什么啊?Apache Ambari or Apache Mesos 。。。
2.集群监控工具也能做些job监控管理的活吧?
回复

使用道具 举报

zzuyao 发表于 2014-12-24 10:09:09
3.楼主上面提到了TaskTracker 是hadoop1.x中的,hadoop2.x中MRAPPMaster会管理task的生命周期,上面的分析提到的创建jvm的活应该交给ApplicationMaster(发送NM命令,启动Contioner)了吧?
回复

使用道具 举报

hb1984 发表于 2014-12-24 11:40:36
谢谢楼主分享。         
回复

使用道具 举报

大数据爱我 发表于 2015-1-5 21:00:02
学习了,楼主幸苦了!
回复

使用道具 举报

bioger_hit 发表于 2015-1-5 21:04:01
zzuyao 发表于 2014-12-24 10:09
3.楼主上面提到了TaskTracker 是hadoop1.x中的,hadoop2.x中MRAPPMaster会管理task的生命周期,上面的分析 ...

这些相信楼主都已经有答案了,实践下就什么都清楚了。
回复

使用道具 举报

ainubis 发表于 2015-3-28 04:50:27
持续关注中。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条