hadoop集群中发现使用Parallel Scavenge+Parallel Old收集器组合进行垃圾收集(这也是server端jvm默认的GC方式)时CPU占用可能会非常高,偶尔会出现爆满的状态,考虑可能是由于当时程序在执行GC导致的,而且很可能是由于并行GC导致的,我们根据服务器启动的Java进程查看一下当前使用的是哪种GC方式:
 
$ jinfo -flag "GC方式" jvm进程id
 
最终可以看出使用的是-XX:+UseParallelOldGC,打开此开关参数后,使用Parallel Scavenge+Parallel Old收集器组合进行垃圾收集。
 
串行垃圾回收器在jvm Client模式下是默认启动的,参数 -XX:+UseSerialGC 可以设置垃圾回收策略为串行。
 
模拟线上同样的两个MR任务,比较其执行CPU时间和GC时间:
 
-XX:+UseParallelOldGC

 
-XX:+UseSerialGC
 
经过分析之后,可以发现GC花费的时间有一定的增长,由453s提高了大概3倍左右,到达1321s;而CPU时间则有大幅度下降,说明的确降低了CPU的时间。
 
为了确保实验结果的正确性,再进行第二次的测试:
 
-XX:+UseParallelOldGC

 
-XX:+UseSerialGC

 
通过对比仍然可以看出,CPU时间减少200s左右,GC时间增加大概260s。通过简单分析可以看出,对于hadoop的每个任务的JVM,更像是client应用程序而非server端的应用,因为每个Task分配的资源CPU: 1 core, 2G memory是相对固定的。

Counter的计算逻辑

 
那么这两个Counter(CPU时间的计算以及GC时间的计算)是如何得出来的?
 
这两个Counter都在hadoop-mapreduce-client包下面的hadoop-mapreduce-client-core模块下,其中的resources包含了所有需要的资源,每个分组都是以不同的.properties文件命名的。CPU和GC消耗时间都在TaskCounter.properties文件中,可以看出这个文件的Counter都属于分组Map-Reduce Framework,在工程中它们存在于具体的枚举中:org.apache.hadoop.mapreduce.TaskCounter,
GC_TIME_MILLIS,
CPU_MILLISECONDS
 
hadoop如何衡量mapreduce任务的计算量,肯定不能按照任务的运行时间来计算,这是由于Map和Reduce的不均匀性,任务可能卡在单个Map或者Reduce端(由于分片和Partition的不均匀性导致)。
 

CPU,内存等资源的计算

 
可以确定,hadoop使用的是CPU时间,CPU_MILLISECONDS就是任务运行耗费的CPU时间。原来在hadoop运行期间,task会从/proc/<pid>/stat读取对应进程的用户CPU时间和内核CPU时间,其总和就是最后的CPU时间。
 
关于proc文件的具体信息说明,可以查看这篇blog:
 
我们关联到具体的源码位置,可以查看下面这个方法:
org.apache.hadoop.mapred.Task void updateResourceCounters()
方法说明:Update resource information counters
其中使用了org.apache.hadoop.yarn.util.ResourceCalculatorProcessTree来获得进程使用的相关资源,其中包括了CPU资源,物理内存以及虚拟内存资源等等。在hadoop2.2.0版本中包括了两种子类型,分别是基于Windows和Linux监测进程资源的,这里只分析基于Linux计算资源的子类:
org.apache.hadoop.yarn.util.ProcfsBasedProcessTree
由于CPU时间都是以jiffies为单位的,因此ProcessTree中首先计算了jiffies:
  • 执行Shell命令:  getconf CLK_TCK,返回jiffiPerseconds=100
  • jiffies的计算公式为:JIFFY_LENGTH_IN_MILLIS = jiffiesPerSecond != -1 ? Math.round(1000D / jiffiesPerSecond) : -1;
而内存占用则摘自上述blog中:
"Map-Reduce Framework:Physical memory (bytes) snapshot" 每个task会从/proc/<pid>/stat读取对应进程的内存快照,这个是进程的当前物理内存使用大小。

"Map-Reduce Framework:Virtual memory (bytes) snapshot" 每个task会从/proc/<pid>/stat读取对应进程的虚拟内存快照,这个是进程的当前虚拟内存使用大小。

"Map-Reduce Framework:Total committed heap usage (bytes)" 每个task的jvm调用Runtime.getRuntime().totalMemory()获取jvm的当前堆大小。
物理内存和虚拟内存是从/proc/pid/stat中拿到的,Total committed heap usage (bytes)是直接调用JDK中的方法Runtime.getRuntime().totalMemory()方法拿到,这个值是这个JVM能拿到的最大内存。
 

GC时间的计算

 
GC时间是肯定不能从系统中得出,这只能寄希望于Java虚拟机。Hadoop中是使用JMX来拿到GC的总时间的,这部分代码可以参考类org.apache.hadoop.mapred.Task类中子类GCTimeUpdater中的构造器以及getElapseGC()方法:
 
public GcTimeUpdater() {
this.gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
getElapsedGc(); // Initialize 'lastGcMillis' with the current time spent.
} /**
* @return the number of milliseconds that the gc has used for CPU
* since the last time this method was called.
*/
protected long getElapsedGc() {
long thisGcMillis = 0;
for (GarbageCollectorMXBean gcBean : gcBeans) {
thisGcMillis += gcBean.getCollectionTime();
} long delta = thisGcMillis - lastGcMillis;
this.lastGcMillis = thisGcMillis;
return delta;
}
JMX,Java Management eXtension,即Java管理扩展,为管理和监测资源提供了一个通过架构,设计模式,API和服务,JMX可以管理和监测的资源包括应用程序、设备、服务和Java虚拟机。
JMX的应用包括但不仅限于以下几种:
  • 管理应用程序的配置;
  • 统计并展现应用程序的行为;
  • 当资源的状态发生变化时发出通知;
比如JDK自带的工具JConsole就是第二种应用的方式:


 
通过其中的GarbageCollectorMBean中的方法就可以监测到具体的收集次数以及收集时间。


 
上述的分析仅仅是关于单个TaskAttempt的counter,这些Counter也需要定时地向Application Master汇报(通过RPC方式以及org.apache.hadoop.mapred.TaskUmbilicalProtocol协议)。
 
任务的Counter刷新也是有一定的间隔的,默认时间间隔(貌似不能修改的):
/** The number of milliseconds between progress reports. */
public static final int PROGRESS_INTERVAL = 3000;
在任务执行过程中会进行不断地刷新操作,任务整体完成后,也会进行最后一次的状态提交,所以我们可以在任务完成后能够查看到所有map/reduce任务成功attemp的Counter指标数据。
 
 
 

hadoop从调整GC到关键Counter计算原理分析的更多相关文章

  1. 【原创 Hadoop&Spark 动手实践 7】Spark 计算引擎剖析与动手实践

    [原创 Hadoop&Spark 动手实践 7]Spark计算引擎剖析与动手实践 目标: 1. 理解Spark计算引擎的理论知识 2. 动手实践更深入的理解Spark计算引擎的细节 3. 通过 ...

  2. Hadoop数据管理介绍及原理分析

    Hadoop数据管理介绍及原理分析 最近2014大数据会议正如火如荼的进行着,Hadoop之父Doug Cutting也被邀参加,我有幸听了他的演讲并获得亲笔签名书一本,发现他竟然是左手写字,当然这个 ...

  3. Hadoop生态圈-Zookeeper的工作原理分析

    Hadoop生态圈-Zookeeper的工作原理分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   无论是是Kafka集群,还是producer和consumer都依赖于Zoo ...

  4. 在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析

    在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析 低成本的Blob存储是一个强大的.通用的Hadoop兼容Azure存储解决方式无缝集成HDInsight.通过Hadoop分布式 ...

  5. 前端移动端的rem适配计算原理

    rem是什么? rem(font size of the root element)是指相对于根元素的字体大小的单位.简单的说它就是一个相对单位.看到rem大家一定会想起em单位,em(font si ...

  6. mapreducer计算原理

    mapreducer计算原理

  7. R语言简单实现聚类分析计算与分析(基于系统聚类法)

    聚类分析计算与分析(基于系统聚类法) 下面以一个具体的例子来实现实证分析.2008年我国其中31个省.市和自治区的农村居民家庭平均每人全年消费性支出. 根据原始数据对我国省份进行归类统计. 原始数据如 ...

  8. OpenGL中摄像机矩阵的计算原理

    熟悉OpenGL|ES的朋友,可能会经常设置摄像机的view矩阵,iOS中相对较好,已经封装了方向,只需要设置摄像机位置,目标点位置以及UP向量即可.下面先介绍下摄像机view矩阵的计算原理.此处假设 ...

  9. Hadoop基础--统计商家id的标签数案例分析

    Hadoop基础--统计商家id的标签数案例分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.项目需求 将“temptags.txt”中的数据进行分析,统计出商家id的评论标 ...

随机推荐

  1. PentesterLab-From SQL Injection to Shell

    一.打开靶机ip出现如下界面: 随便点一下,点到test链接,访问了如下url:http://192.168.109.131/cat.php?id=1,这里出现了一个id,常规思路这个位置可能有sql ...

  2. APUE学习笔记——5.9Binary I/O 二进制读写

    概述:         二进制I/O,通常用来一次性读写结构化的数据块.(因为有时候我们要读写的数据中包含换行符或者Null字符,无法使用fgets或fputs,而使用getc和putc又需要花费太多 ...

  3. ROW_NUMBER() OVER(PARTITION BY)

    select * from (select *,ROW_NUMBER() OVER(PARTITION BY GoodsID ORDER BY IsMain desc,OrderNum) as Mai ...

  4. vue.js 源代码学习笔记 ----- $watcher

    /* @flow */ import { queueWatcher } from './scheduler' import Dep, { pushTarget, popTarget } from '. ...

  5. Android常见问题——Genymotion无法启动问题

    在官网下载了Genymotion和VirturalBox的合集安装之后启动模拟器的时候发现启动不了(默认下载,啥都没干),在网上找了一些方法,也没有解决,最后偶然看到一种方法才解决的,先看一下具体的问 ...

  6. python中处理命令行参数的模块optpars

    optpars是python中用来处理命令行参数的模块,可以自动生成程序的帮助信息,功能强大,易于使用,可以方便的生成标准的,符合Unix/Posix 规范的命令行说明.使用 add_option() ...

  7. boost::function和boost:bind取代虚函数

    以boost::function和boost:bind取代虚函数 这是一篇比较情绪化的blog,中心思想是"继承就像一条贼船,上去就下不来了",而借助boost::function ...

  8. vue-router(一)

    vue路由再vue开发的项目中可以说是一个必用的组件,而这个部分的水却依旧很深,今天我们深入分析其内部的东西,先看这样一个效果: 大家 可以看到上图中,我们通过两种方式实现了一个vue路由跳转的过度动 ...

  9. BZOJ1098 POI2007 办公楼biu 【链表+bfs】

    Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决 ...

  10. Codeforces 834D The Bakery 【线段树优化DP】*

    Codeforces 834D The Bakery LINK 题目大意是给你一个长度为n的序列分成k段,每一段的贡献是这一段中不同的数的个数,求最大贡献 是第一次做线段树维护DP值的题 感觉还可以, ...