博客
关于我
从Container内存监控限制到CPU使用率限制方案
阅读量:384 次
发布时间:2019-03-05

本文共 4804 字,大约阅读时间需要 16 分钟。

前言

最近在运维我们部门的Hadoop集群时,发现了很多Job OOM的现象。频繁的Full GC导致了严重的性能问题。Full GC会导致“stop the world”,一旦Full GC的时间超过几分钟,其他活动都会受到影响。因此,必须找到原因并解决它。本文将介绍我们是如何解决这个问题,并在此基础上进行了一些优化。

Full GC源于何处

OOM的发生导致频繁的Full GC。首先需要确定具体原因。通常,第一个联想是上面的Job,Job的运行表现来自每个Task,而每个Task又表现为每个TaskAttempt。TaskAttempt运行在申请到的Container中。每个Container是一个独立的进程,可以通过jps命令在DataNode上看到大量名为“YarnChild”的进程,这些进程就是Container的启动进程。

初步估计是Container启动的JVM内存配置不足,导致内存不足。但问题并没有这么简单,这里还有些复杂。

为什么会发生Full GC

  • 内存配置不当:MapReduce任务的内存配置默认为1024MB(即1GB),但这可能不够,尤其是在处理大数据量或复杂任务时。错误的配置也可能导致JVM无法使用所需内存,从而引发OOM。

  • JVM配置错误:虽然mapreduce.map.memory.mbmapreduce.reduce.memory.mb是MapReduce任务的内存配置,但实际上它们并不是Container启动的JVM的内存配置。JVM的内存上限由mapreduce.map.java.optsmapreduce.reduce.java.opts决定。因此,理想的配置是java.opts的值必须大于等于memory.mb的值。如果配置不当,也会引发频繁的Full GC。

  • Container内存监控

    幸运的是,Hadoop已经对Container级别的内存进行了监控。对于所有启动的Container,Hadoop会额外启动一个名为container-monitor的线程,专门监控这些Container的物理内存和虚拟内存使用情况。相关的配置项包括:

    • yarn.nodemanager.pmem-check-enabled
    • yarn.nodemanager.vmem-check-enabled

    默认情况下,这两项都启用。内存监控的作用是一旦Container使用的内存超过JVM的最大内存上限,Container会被杀死。

    通过分析ContainersMonitorImpl.java可以看出,监控线程会在每隔一定时间(由YarnConfiguration.NM_CONTAINER_MON_INTERVAL_MS控制)遍历所有被监控的Container,检查它们的内存使用情况。如果内存使用超过限制,Container会被杀死。

    为什么只对Container内存做监控

    在解决上述问题后,我开始思考为什么不对CPU使用率也进行监控。同样重要的指标,CPU使用率为什么不一起监控呢?

    我总结了以下几点原因:

  • 影响更大:内存问题比CPU使用率问题影响更大,因为OOM会导致Full GC,一旦发生Full GC,整个应用都会受到影响。
  • 更常见:内存问题比CPU使用率问题更常见。大家在日常生活或编写程序时,更容易遇到内存不足的问题,而不是CPU不足的问题。
  • 密切相关:内存使用与Job处理的数据量密切相关。处理大数据量的Job,内存使用自然会更多,CPU使用率也会增加,但不会那么明显。
  • 综上所述,CPU监控并未被加入到监控代码中(个人分析)。但Hadoop自身并未加CPU监控并不代表我们不能添加这样的监控功能。例如,对于那些内存并不多,但会耗尽大量CPU资源的程序(如开很多线程但每个线程都做简单操作的程序),添加CPU使用率监控会有帮助。

    Container的Cpu使用率监控

    为了实现对CPU使用率的监控,我们需要:

  • 定义是否启用CPU使用率监控的配置:
  • /** Specifies whether cpu vcores check is enabled. */public static final String NM_VCORES_CHECK_ENABLED = NM_PREFIX + "vcores-check-enabled";public static final boolean DEFAULT_NM_VCORES_CHECK_ENABLED = false;

    默认情况下,CPU使用率监控是关闭的。同时,还需要定义一个使用阈值(0~1之间),一旦某个Container的CPU使用率超过这个阈值,Container就会被杀死。

    1. 定义CPU使用率的限制比例:
    2. /** Limit ratio of Virtual CPU Cores which can be allocated for containers. */public static final String NM_VCORES_LIMITED_RATIO = NM_PREFIX + "resource.cpu-vcores.limited.ratio";public static final float DEFAULT_NM_VCORES_LIMITED_RATIO = 0.8f;

      默认值为0.8,可以根据需要进行调整。

      1. serviceInit方法中进行配置初始化:
      2. private boolean pmemCheckEnabled;private boolean vmemCheckEnabled;private boolean vcoresCheckEnabled;private float vcoresLimitedRatio;...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);vcoresCheckEnabled = conf.getBoolean(YarnConfiguration.NM_VCORES_CHECK_ENABLED, YarnConfiguration.DEFAULT_NM_VCORES_CHECK_ENABLED);LOG.info("Physical memory check enabled: " + pmemCheckEnabled);LOG.info("Virtual memory check enabled: " + vmemCheckEnabled);LOG.info("Cpu vcores check enabled: " + vcoresCheckEnabled);if (vcoresCheckEnabled) {    vcoresLimitedRatio = conf.getFloat(YarnConfiguration.NM_VCORES_LIMITED_RATIO, YarnConfiguration.DEFAULT_NM_VCORES_LIMITED_RATIO);    LOG.info("Vcores limited ratio: " + vcoresLimitedRatio);}
        1. 在监控代码中使用计算出的CPU使用率进行判断:
        2. LOG.debug("Constructing ProcessTree for : PID = " + pId + " ContainerId = " + containerId);ResourceCalculatorProcessTree pTree = ptInfo.getProcessTree();pTree.updateProcessTree();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. } else if (isVcoresCheckEnabled() && cpuUsageTotalCoresPercentage > vcoresLimitedRatio) {    msg = String.format(        "Container [pid=%s,containerID=%s] is running beyond %s vcores limits."            + " Current usage: %s. Killing container.\n", pId,        containerId, vcoresLimitedRatio);    isCpuVcoresOverLimit = true;    containerExitStatus = ContainerExitStatus.KILLED_EXCEEDED_VCORES;}if (isMemoryOverLimit || isCpuVcoresOverLimit) {    // Virtual or physical memory over limit. Fail the container and    // remove the corresponding process tree    LOG.warn(msg);    // warn if not a leader    if (!pTree.checkPidPgrpidForMatch()) {        LOG.error("Killed container process with PID " + pId            + " but it is not a process group leader.");    }    // kill the container    eventDispatcher.getEventHandler().handle(        new ContainerKillEvent(containerId, containerExitStatus, msg));    it.remove();    LOG.info("Removed ProcessTree with root " + pId);} else {

            相关链接

    转载地址:http://gvng.baihongyu.com/

    你可能感兴趣的文章
    Node-RED中实现HTML表单提交和获取提交的内容
    查看>>
    Node-RED中将CSV数据写入txt文件并从文件中读取解析数据
    查看>>
    Node-RED中建立TCP服务端和客户端
    查看>>
    Node-RED中建立Websocket客户端连接
    查看>>
    Node-RED中建立静态网页和动态网页内容
    查看>>
    Node-RED中解析高德地图天气api的json数据显示天气仪表盘
    查看>>
    Node-RED中连接Mysql数据库并实现增删改查的操作
    查看>>
    Node-RED中通过node-red-ui-webcam节点实现访问摄像头并截取照片预览
    查看>>
    Node-RED中配置周期性执行、指定时间阶段执行、指定时间执行事件
    查看>>
    Node-RED安装图形化节点dashboard实现订阅mqtt主题并在仪表盘中显示温度
    查看>>
    Node-RED怎样导出导入流程为json文件
    查看>>
    Node-RED订阅MQTT主题并调试数据
    查看>>
    Node-RED通过npm安装的方式对应卸载
    查看>>
    node-request模块
    查看>>
    node-static 任意文件读取漏洞复现(CVE-2023-26111)
    查看>>
    Node.js 8 中的 util.promisify的详解
    查看>>
    node.js debug在webstrom工具
    查看>>
    Node.js HTTP模块详解:创建服务器、响应请求与客户端请求
    查看>>
    Node.js RESTful API如何使用?
    查看>>
    node.js url模块
    查看>>