JS技术

从Container内存监控限制到CPU使用率限制方案 - 走在前往架构师的路上 - 博客频道 - CSDN.NET 走

字号+ 作者:H5之家 来源:H5之家 2015-12-15 09:09 我要评论( )

build target存在于android项目中的工程文件project.properties中,是eclipse自动创建(build)工程时用到的一个设置。project.properties文件代码minSdkVersion

前言

最近在运维我们部门的hadoop集群时,发现了很多Job OOM的现象,因为在机器上可以用命令进行查看,full gc比较严重.我们都知道,full gc带来的后果是比较大的,会"stop the world"的,一旦你的full gc elapsed time超过几分钟,那么其他的活动都得暂停这么多时间.所以Full gc一旦出现并且异常,一定要找到根源并将其解决.本篇文章就为大家讲述一下我们是如何解决这类问题并且在这个基础上做了一些别的什么优化的.


Full Gc源于何处

OOM发生了,导致频繁的Full Gc的现象,首先就要想到底是什么导致Full gc.第一个联想一定是上面跑的Job,Job的运行时的体现又是从每个task身上来的,而每个Task又是表现于每个TaskAttempt.而TaskAttempt是跑在所申请到的container中的.每个container都是一个独立的进程,你可以在某台datanode上用jps命令,可以看到很多叫"YarnChild"的进程,那就是container所起的.找到了源头之后,我们估计会想,那应该是container所启的jvm的内存大小配小了,导致内存不够用了,内存配大些不就可以解决问题了?事实上问题并没有这么简单,这里面的水还是有点深的.


为什么会发生Full Gc

一.为什么会发生full gc,第一种原因就是平常大家所说的内存配小了,就是下面2个配置项:

public static final String MAP_MEMORY_MB = "mapreduce.map.memory.mb";public static final String REDUCE_MEMORY_MB = "mapreduce.reduce.memory.mb";默认都是1024M,就是1个G.

二.另外一个原因估计想到的人就不太多了,除非你真的在生活中碰到过,概况来说一句话:错误的配置导致.上面的这个配置其实并不是container设置他所启的jvm的配置,而是每个Task所能用的内存的上限值,但是这里会有个前提,你的jvm必须保证可以用到这么多的内存,如果你的jvm最大内存上限就只有512M,你的task的memory设的再大也没有,最后造成的直接后果就是内存一用超,就会出现full gc.上面的2个值更偏向于理论值.而真正掌控jvm的配置项的其实是这2个配置:

public static final String MAP_JAVA_OPTS = "mapreduce.map.java.opts";public static final String REDUCE_JAVA_OPTS = "mapreduce.reduce.java.opts";所以理想的配置应该是java.opts的值必须大于等于memory.mb的值.所以说,这种配置不当的方式也会引发频繁的full gc.


Container内存监控

不过比较幸运的是针对上面所列举的第二种问题,hadoop自身已经对此进行了contaienr级别的监控,对于所有启动过container,他会额外开启一个叫container-monitor的线程,专门有对于这些container的pmem(物理内存),vmem(虚拟内存)的监控.相关的配置属于如下:

String org.apache.hadoop.yarn.conf.YarnConfiguration.NM_PMEM_CHECK_ENABLED = "yarn.nodemanager.pmem-check-enabled" String org.apache.hadoop.yarn.conf.YarnConfiguration.NM_VMEM_CHECK_ENABLED = "yarn.nodemanager.vmem-check-enabled" 默认都是开启的.内存监控的意思就是一旦这个container所使用的内存超过这个jvm本身所能使用的最大上限值,则将此conyainer kill掉.下面简单的从源代码的级别为大家分析一下,过其实不难.首先进入到ContainersMonitorImpl.java这个类.

@Override protected void serviceInit(Configuration conf) throws Exception { this.monitoringInterval = conf.getLong(YarnConfiguration.NM_CONTAINER_MON_INTERVAL_MS, YarnConfiguration.DEFAULT_NM_CONTAINER_MON_INTERVAL_MS); .... pmemCheckEnabled = conf.getBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, YarnConfiguration.DEFAULT_NM_PMEM_CHECK_ENABLED); vmemCheckEnabled = conf.getBoolean(YarnConfiguration.NM_VMEM_CHECK_ENABLED, YarnConfiguration.DEFAULT_NM_VMEM_CHECK_ENABLED); LOG.info("Physical memory check enabled: " + pmemCheckEnabled); LOG.info("Virtual memory check enabled: " + vmemCheckEnabled); ....在serviceInit方法中就会从配置中读取是否开启内存监控功能,并输出日志信息.然后我们直接进入到此类的MonitorThread监控线程类中.

.... private class MonitoringThread extends Thread { public MonitoringThread() { super("Container Monitor"); } @Override public void run() { while (true) { // Print the processTrees for debugging. if (LOG.isDebugEnabled()) { StringBuilder tmp = new StringBuilder("[ "); for (ProcessTreeInfo p : trackingContainers.values()) { tmp.append(p.getPID()); tmp.append(" "); } ....在监控线程的run方法中,他会对所监控的container做遍历判断处理

@Override public void run() { while (true) { .... // Now do the monitoring for the trackingContainers // Check memory usage and kill any overflowing containers long vmemStillInUsage = 0; long pmemStillInUsage = 0; for (Iterator<Map.Entry<ContainerId, ProcessTreeInfo>> it = trackingContainers.entrySet().iterator(); it.hasNext();) { Map.Entry<ContainerId, ProcessTreeInfo> entry = it.next(); ContainerId containerId = entry.getKey(); ProcessTreeInfo ptInfo = entry.getValue(); try { String pId = ptInfo.getPID(); ....我们以物理内存监控的原理实现为一个例子.

首先他会根据pTree拿到进程相关的运行信息,比如内存,CPU信息等

LOG.debug("Constructing ProcessTree for : PID = " + pId + " ContainerId = " + containerId); ResourceCalculatorProcessTree pTree = ptInfo.getProcessTree(); pTree.updateProcessTree(); // update process-tree long currentVmemUsage = pTree.getVirtualMemorySize(); long currentPmemUsage = pTree.getRssMemorySize(); // if machine has 6 cores and 3 are used, // cpuUsagePercentPerCore should be 300% and // cpuUsageTotalCoresPercentage should be 50% float cpuUsagePercentPerCore = pTree.getCpuUsagePercent(); float cpuUsageTotalCoresPercentage = cpuUsagePercentPerCore / resourceCalculatorPlugin.getNumProcessors();然后拿到内存使用上限值

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 关于ie的内存泄漏与javascript内存释放_javascript教程教程

    关于ie的内存泄漏与javascript内存释放_javascript教程教程

    2015-10-07 11:10

  • 在IE下JS编程应注意的内存释放问题_Javascript教程

    在IE下JS编程应注意的内存释放问题_Javascript教程

    2015-10-02 18:19

  • data()方法避免内存泄露问题_Javascript教程

    data()方法避免内存泄露问题_Javascript教程

    2015-10-01 11:22

  • javascript与内存

    javascript与内存

    2014-11-17 20:00

网友点评
d