从Container内存监控限制到CPU使用率限制方案

前言

最近在运维我们部门的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.isDebugEnab
阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以在 Docker Compose 文件中为服务指定 CPU内存限制。下面是一个可以参考的示例,其中为 flow-server 服务指定了 2 个 CPU 核心和 1GB 内存: ``` version: '3' services: flow-nginx: container_name: flow-nginx image: nginx build: context: . dockerfile: nginx-dockerfile ports: - "80:80" environment: TZ: Asia/Shanghai volumes: - ./html/dist:/home/flow/projects/ruoyi-ui - ./conf/nginx.conf:/etc/nginx/nginx.conf - ./home/nginx/logs:/var/log/nginx - ./home/nginx/conf.d:/etc/nginx/conf.d depends_on: - flow-server links: - flow-server networks: - base-docker_flownet flow-server: container_name: flow-server build: context: . dockerfile: flow-dockerfile ports: - "8080:8089" environment: TZ: Asia/Shanghai volumes: - ./home/flow/logs:/home/flow/logs - ./home/flow/uploadPath:/home/flow/uploadPath - /home/flow/flow_ftp:/home/flow/flow_ftp networks: - base-docker_flownet deploy: resources: limits: cpus: '2' memory: 1g reservations: cpus: '1' memory: 500m ``` 为了设置资源限制,我们在 flow-server 服务中使用了 deploy 部分,其中,limits 指定了服务的 CPU内存限制,reservations 则指定了服务的 CPU内存保留量。在这里,我们将服务的 CPU 核心数限制为 2,内存限制为 1GB,而 CPU内存的保留量分别设置为 1 个核心和 500MB。这意味着,服务会在最少占用 1 个核心和 500MB 内存的前提下,最多能够使用 2 个核心和 1GB 内存。您可以根据您的实际需求,调整这些值。 请注意,如果您的服务器的 CPU 占用率已经达到了 90%,那么对 Docker 容器进行资源限制是无法解决这个问题的。您需要考虑优化您的代码或者增加服务器资源才能解决这个问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Android路上的人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值