MRv2内存监控强杀Container问题解决

线上某个hive job运行失败,报错如下

    Container [pid=28474,containerID=container_1411897705890_0181_01_000012] is running beyond physical memory limits. Current usage: 1.0 GB of 1 GB physical memory used; 1.5 GB of 2.1 GB virtual memory used. Killing container.
Dump of the process-tree for container_1411897705890_0181_01_000012 :
        |- PID PPID PGRPID SESSID CMD_NAME USER_MODE_TIME(MILLIS) SYSTEM_TIME(MILLIS) VMEM_USAGE(BYTES) RSSMEM_USAGE(PAGES) FULL_CMD_LINE
        |- 28474 19508 28474 28474 (bash) 0 0 9416704 309 /bin/bash -c /usr/java/jdk1.7.0_67/bin/java -Djava.net.preferIPv4Stack=true -Dhadoop.metrics.log.level=WARN  -Xmx1024m -Djava.io.tmpdir=/data/yarn/local/usercache/hadoop/appcache/application_1411897705890_0181/container_1411897705890_0181_01_000012/tmp -Dlog4j.configuration=container-log4j.properties -Dyarn.app.container.log.dir=/data/yarn/logs/application_1411897705890_0181/container_1411897705890_0181_01_000012 -Dyarn.app.container.log.filesize=0 -Dhadoop.root.logger=INFO,CLA org.apache.hadoop.mapred.YarnChild 10.10.11.161 32875 attempt_1411897705890_0181_r_000000_3 12 1>/data/yarn/logs/application_1411897705890_0181/container_1411897705890_0181_01_000012/stdout 2>/data/yarn/logs/application_1411897705890_0181/container_1411897705890_0181_01_000012/stderr  
        |- 28481 28474 28474 28474 (java) 2356 397 1630285824 264098 /usr/java/jdk1.7.0_67/bin/java -Djava.net.preferIPv4Stack=true -Dhadoop.metrics.log.level=WARN -Xmx1024m -Djava.io.tmpdir=/data/yarn/local/usercache/hadoop/appcache/application_1411897705890_0181/container_1411897705890_0181_01_000012/tmp -Dlog4j.configuration=container-log4j.properties -Dyarn.app.container.log.dir=/data/yarn/logs/application_1411897705890_0181/container_1411897705890_0181_01_000012 -Dyarn.app.container.log.filesize=0 -Dhadoop.root.logger=INFO,CLA org.apache.hadoop.mapred.YarnChild 10.10.11.161 32875 attempt_1411897705890_0181_r_000000_3 12

根据异常分析应该是内存使用超过限制,ContainersMonitorImpl将进程kill导致的,查看下JVM内存回收的情况

[GC [PSYoungGen: 241753K->16036K(306176K)] 241753K->16116K(1005568K), 0.0362550 secs] [Times: user=0.31 sys=0.05, real=0.04 secs] 
[GC [PSYoungGen: 210741K->4826K(306176K)] 210821K->282228K(1005568K), 0.0996080 secs] [Times: user=1.58 sys=0.15, real=0.10 secs] 
[GC [PSYoungGen: 194630K->4762K(306176K)] 472032K->624439K(1005568K), 0.1418910 secs] [Times: user=2.30 sys=0.14, real=0.14 secs] 
[Full GC [PSYoungGen: 4762K->0K(306176K)] [ParOldGen: 619677K->359650K(699392K)] 624439K->359650K(1005568K) [PSPermGen: 21635K->21622K(43520K)], 0.1742260 secs] [Times: user=0.82 sys=0.07, real=0.17 secs] 
[GC-- [PSYoungGen: 192581K->192581K(306176K)] 655085K->833707K(1005568K), 0.0634170 secs] [Times: user=1.08 sys=0.00, real=0.06 secs] 
[Full GC [PSYoungGen: 192581K->0K(306176K)] [ParOldGen: 641125K->640707K(699392K)] 833707K->640707K(1005568K) [PSPermGen: 21674K->21674K(49152K)], 0.0663990 secs] [Times: user=0.65 sys=0.05, real=0.07 secs] 
[Full GC [PSYoungGen: 262656K->0K(306176K)] [ParOldGen: 640709K->8142K(699392K)] 903365K->8142K(1005568K) [PSPermGen: 24649K->24647K(49152K)], 0.0662210 secs] [Times: user=0.37 sys=0.00, real=0.07 secs] 
[GC [PSYoungGen: 262656K->15936K(327680K)] 270798K->24078K(1027072K), 0.0175890 secs] [Times: user=0.14 sys=0.14, real=0.02 secs] 
Heap
 PSYoungGen      total 327680K, used 201250K [0x00000000eaa80000, 0x0000000100000000, 0x0000000100000000)
  eden space 284160K, 65% used [0x00000000eaa80000,0x00000000f5f78b18,0x00000000fc000000)
  from space 43520K, 36% used [0x00000000fd580000,0x00000000fe510010,0x0000000100000000)
  to   space 22016K, 0% used [0x00000000fc000000,0x00000000fc000000,0x00000000fd580000)
 ParOldGen       total 699392K, used 8142K [0x00000000bff80000, 0x00000000eaa80000, 0x00000000eaa80000)
  object space 699392K, 1% used [0x00000000bff80000,0x00000000c07738d8,0x00000000eaa80000)
 PSPermGen       total 49152K, used 24726K [0x00000000bad80000, 0x00000000bdd80000, 0x00000000bff80000)
  object space 49152K, 50% used [0x00000000bad80000,0x00000000bc5a5908,0x00000000bdd80000)

并没有明显的内存泄露或者内存溢出的情况,还是从堆内存入手,由于MR JOB的对象生存周期普遍比较短,尝试调大新生代,让更多对象在新生代进行回收,提高回收的效率,参数调整为

-Xms1024m -Xmx1024m -Xmn600m

问题解决。这次遇到的是物理内存超过限制的问题,还有一种是虚拟内存超过限制导致任务被kill

参数yarn.nodemanager.vmem-pmem-ratio的含义是每单位的物理内存总量对应的虚拟内存量,默认是2.1,表示每使用1MB的物理内存,最多可以使用2.1MB的虚拟内存总量,解决虚拟内存问题可以适当调高该参数或者还从JVM内存回收方面来优化。

最后说下ContainersMonitorImpl的监控策略,它保存了每个Container的pid,内部的MonitoringThread线程每隔一段时间扫描运行的Container进程树。NodeManager通过读取/proc/<pid>/stat文件构造以该Container进程为根的进程树,通过监控进程树使用的内存量来限制任务的内存量。

private class MonitoringThread extends Thread {

    public void run() {
      while (true) {
          //获取进程树
          ResourceCalculatorProcessTree pTree = ptInfo.getProcessTree();
          pTree.updateProcessTree();
          //获取container进程树的内存使用量
          long currentVmemUsage = pTree.getCumulativeVmem();
          long currentPmemUsage = pTree.getCumulativeRssmem();
          //获取进程树中年龄大于1的进程的内存使用量
          long curMemUsageOfAgedProcesses = pTree.getCumulativeVmem(1);
          long curRssMemUsageOfAgedProcesses = pTree.getCumulativeRssmem(1);
          long vmemLimit = ptInfo.getVmemLimit();
          long pmemLimit = ptInfo.getPmemLimit();
          boolean isMemoryOverLimit = false;
            String msg = "";
            //如果一个Container进程树中所有进程(年龄大于0)总内存超过设置最大值的两倍或者
            //年龄大于1的进程总内存量超过设置最大值,则将该Container杀死
            if (isVmemCheckEnabled()
                && isProcessTreeOverLimit(containerId.toString(),
                    currentVmemUsage, curMemUsageOfAgedProcesses, vmemLimit)) {
              msg = formatErrorMessage("virtual",
                  currentVmemUsage, vmemLimit,
                  currentPmemUsage, pmemLimit,
                  pId, containerId, pTree);
              isMemoryOverLimit = true;
            } else if (isPmemCheckEnabled()
                && isProcessTreeOverLimit(containerId.toString(),
                    currentPmemUsage, curRssMemUsageOfAgedProcesses,
                    pmemLimit)) {
              msg = formatErrorMessage("physical",
                  currentVmemUsage, vmemLimit,
                  currentPmemUsage, pmemLimit,
                  pId, containerId, pTree);
              isMemoryOverLimit = true;
            }
      }
    }

所有有些时候并不是某个JVM进程的堆内存溢出才可以导致Task被kill,需要调整好对应参数才行,堆内存也并不是越大越好,调整好各代所占的比例也很重要。

时间: 2024-08-25 16:47:11

MRv2内存监控强杀Container问题解决的相关文章

使用Flask结合python实现多台服务的内存监控

使用Flask结合python实现多台服务的内存监控   简介:使用flask结合python可以很好的实现服务资源的监控,而且Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 .Flask使用 BSD 授权. 接下来我们实现多台服务器的内存监控,并出图. 环境:centos1-6.5  ip:172.25.0.31   ##做flask python数据获取 Centos2-6.5  ip:172.2

iOS微信内存监控

WeTest 导读 目前iOS主流的内存监控工具是Instruments的Allocations,但只能用于开发阶段.本文介绍如何实现离线化的内存监控工具,用于App上线后发现内存问题. FOOM(Foreground Out Of Memory),是指App在前台因消耗内存过多引起系统强杀.对用户而言,表现跟crash一样.Facebook早在2015年8月提出FOOM检测办法,大致原理是排除各种情况后,剩余的情况是FOOM,具体链接:https://code.facebook.com/pos

10min 手写一个内存监控系统

本文的目的在于,尽可能用简单的代码,让大家了解内存监控的原理,及思想.更容易去理解Nagios.Zabbix.Ganglia监控原理,文章最后还有视频教程链接哦,从零敲出来的全过程 思路分为下面几块: 1.获取内存监控信息 2.存储监控信息 3.数据展现 4.后续扩展 1.加主机名,monitor部署在多台机器,不直接插入数据库 2. 增加CPU,Disk监控 3. 通过HTTP请求的方式,启用一个单独的Flask专门存储monitor数据 第一步:获取内存信息 我们通过读取 /proc/mem

AWS Centos磁盘和内存监控脚本

在centos上使用aws硬盘和内存监控脚本,会发现脚本出错,无法正常工作,这是因为aws的官方文档中提到脚本没有在centos上做过测试,并不能保证脚本能使用 如何解决呢,需要安装以下软件: yum install -y perl-CPAN       exportPERL_MM_USE_DEFAULT=1 # setup defaultconfig perl -MCPAN -e shell #进入MCPAN Shell,自动生成默认配置,并退出       # 类似于yum,下载安装各种包,

Zabbix 3.0 监控交换机(3)--CPU、内存监控及配置Trigger

要监控交换机的CPU.内存关键在于找到正确的OID,关于怎么寻找OID请参考以下博文. http://tryrus.blog.51cto.com/10914693/1788833 看这篇博文之前请确定已对zabbix的基本操作已有了解,有不明白的地方可以看我之前写的博文. http://tryrus.blog.51cto.com/10914693/1772271 http://tryrus.blog.51cto.com/10914693/1782062 一.配置环境 CentOS 7 Linux

MySQL 内存监控

上一篇blog介绍了因为sql查询information_schema表而导致内存暴涨的case. 今天顺便做了一个thd内存的监控: 先来介绍下MySQL的内存: 1. 线程内内存:thd->mem_root, 线程在执行sql的过程中,申请的内存从thd->mem_root进行分配,在sql结束的时候释放. 2. 线程外内存:对象专有的mem_root; 比如,table, table_share,st_transactions等都有专有的mem_root. 所以: 对于sql引起的内存暴

操作系统性能监控之内存监控

操作系统性能监控 服务端程序除了应用本身性能外,依赖与服务器本身的性能.服务器性能指标包括:CPU.内存.网络IO和磁盘使用率. 今天学习了内存监控的部分. 为什么要监测内存 当应用运行所需内存超过可用物理内存时,就会发生页面交换.通常会在硬盘上分配一个swap空间.当应用耗尽可用内存时,就会把不常用的内容放到swap空间里. 当访问被置换到swap空间的内容时,就需要把swap空间的内容加载到物理内存中,这种置换操作会大大影响应用的吞吐量和响应性. JVM垃圾收集器在进行置换操作时,性能也很差

Linux 内存监控

init进程是系统中的第一个进程,PID永远为1 查看系统在中静态进程的统计信息 命令: ps 格式: ps [可选项] ax: 显示所有的进程信息 -u: 使用以用户为主的格式输出进程信息 -e: select all processes 显示系统内的进程信息 -l: 使用长格式显示进程信息 -f: full 使用完整的格式显示进程信息 ps aux命令 [[email protected] tmp]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT ST

c++ 对特定进程的内存监控

在工具实现的过程中,遇到了内存爆了的问题,部分模型的规模可以达到10的100次方方甚至1000次方.(工具的主要算法涉及到了递归,递归深度会很深,所以也用到了ulimit修改栈空间来缓解爆栈的问题,治标不治本.)有一个循环,这个循环迭代16次,但是可能程序在某一次迭代过程中,已经耗光了内存,再申请空间的时候,出现异常,导致将整个进程杀死.而我的想法是,当某一个迭代过程中,出现无法再申请内存的情况,就输出内存申请失败的提示信息,并跳过它,进行下一次的迭代,而不是将整个进程kill. 解决方法:创建