首页 > 系统相关 >Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程

时间:2024-01-09 14:32:54浏览次数:41  
标签:ResourceManager 100% Hadoop private hadoop RenewerPoolTracker future new public

1. top命令查看进程占用 CPU 情况

top

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_java

2. 查找该进程号(22054)对应的服务

方式一:top 命令输入后,再按键盘中的 “c” 字母即可查看

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_java_02

方式二:使用: ps -ef | grep PID 命令查看

ps -ef | grep 22054

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_hadoop_03

3.找到该进程中占用 CPU 最高的线程

top -Hp 22054

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_java_04

4. 将线程的ID转换为16进制(用于排查、匹配进程的堆栈信息)

printf "%x\n" 22545

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_java_05

5. 使用 jstack 命令(java 自带命令)查看对应进程的堆栈信息,找出问题代码

使用 jstack 22054 | grep "5811" -A 30 查看具体的进程信息。

jstack:Prints Java thread stack traces for a Java process, core file, or remote debug server。

其中 grep -A 30 则是显示(上下文,也就是上下行)下文30条相关的语句

使用进程的启动用户(yarn)执行该命令

sudo su - yarn
jstack 22054 | grep "5811" -A 30

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_hadoop_06

截图中指向 DelegationTokenRenewer类中的DelegationTokenRenewerPoolTracker类中的 run方法,有问题的代码在 990行!

6.查看代码,分析问题

因为这是 hadoop 的源码,可以在 github上直接在线查询对应版本的代码或者下载对应版本代码在本地 idea中打开查看,我们使用的hadoop 版本是:3.3.4,找的对应代码,如下:

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_java_07

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_java_08

看似没问题,其实有问题,因为这个类是给集群中开启了 Kerberos 认证的用户更新用户有效凭证的,并且会在任务提交后立即执行,同时会一直等待着主体过期后再次更新主体的有效时间,避免任务在执行过程中因为 token 失效而导致任务执行失败。

但是这个 while(true) 方法就是导致 CPU 一直被占用的关键,当 map集合中没有数据的时候,一直跑的 while(true)代码,让 cpu 空转,拿着一个 CPU 不放。

7. 解决问题

因为这是 hadoop 版本自带的问题。一种方式是等待 hadoop 版本升级后优化掉这个问题后再部署新版本,另一种方式是自己修改源码、再编译打包部署,这种方式稳定性不保证。

github 上 hadoop 的代码已有人遇到同样的问题并自己做了修改优化,但他的代码目前未能合并到 hadoop的最新版本分支中。

同时在 hadoop的 trunk 分支中已经做了另一种更优雅的方式来优化和修改,可等 hadoop 新版本发布。

参考资料:

https://github.com/apache/hadoop/pull/4435

https://issues.apache.org/jira/browse/YARN-11178?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel

https://github.com/apache/hadoop/blob/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/DelegationTokenRenewer.java

社区开发者的解决方式:

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_java_09

hadoop 官方的解决方式:

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_hadoop_10

Hadoop 的 ResourceManager进程占用 CPU 100% 问题排查过程_java_11

8.手动复现此问题

8.1. hadoop 旧版本问题对应的简化代码示例

package com.example.demo.futuretracker;

import java.util.Map;
import java.util.concurrent.*;

/**
 * 问题点:run方法中的 while(true)当 map 集合中无数据的时候会一直运行,占用着 CPU 不放。
 */
public class FutureTrackerExample {
    private final Map<String, Future<?>> futures = new ConcurrentHashMap<>();
    private final long tokenRenewerThreadTimeout = 60;

    private final class RenewerPoolTracker implements Runnable {

        @Override
        public void run() {
            while (true) {
                for (Map.Entry<String, Future<?>> entry : futures.entrySet()) {
                    String key = entry.getKey();
                    Future<?> future = entry.getValue();
                    try {
                        future.get(tokenRenewerThreadTimeout, TimeUnit.MILLISECONDS);
                    } catch (TimeoutException e) {
                        // Handle TimeoutException, retry logic can be added here
                        System.out.println("Timeout occurred for key: " + key);
                    } catch (InterruptedException | ExecutionException ex) {
                        ex.printStackTrace();
                        // Handle other exceptions if needed
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        FutureTrackerExample example = new FutureTrackerExample();
        RenewerPoolTracker renewerPoolTracker = example.new RenewerPoolTracker();
        Thread trackerThread = new Thread(renewerPoolTracker);
        trackerThread.start();
    }
}

8.2. 社区开发者提供的解决方法代码示例

package com.example.demo.futuretracker;

import java.util.Map;
import java.util.concurrent.*;

/**
 * 优化点:在run方法中的 while(true)动作之前判断 map 集合中是否为空,
 *        为空则手动调用 wait 方法等待一段时间,等待后再次判断map 集合中是否为空,
 *        为空则继续判断、等待,重复此步骤。
 * 解决思路:在集合为空的情况下,手动调用 wait方法,让出 cpu 一段时间,此期间不持有锁,
 *         并重复此步骤。直到集合中有任务则正常执行。
 *
 */
public class FutureTrackerExample1 {
    private final Map<String, Future<?>> futures = new ConcurrentHashMap<>();
    private final long tokenRenewerThreadTimeout = 60;

    private final class RenewerPoolTracker implements Runnable {

        @Override
        public void run() {
            while (true) {
                if (futures.isEmpty()) {
                    synchronized (this) {
                        try {
                            long waitingTimeMs = Math.min(10000, Math.max(500, tokenRenewerThreadTimeout));
                            this.wait(waitingTimeMs);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    if (futures.isEmpty()) {
                        continue;
                    }
                }

                for (Map.Entry<String, Future<?>> entry : futures.entrySet()) {
                    String key = entry.getKey();
                    Future<?> future = entry.getValue();
                    try {
                        future.get(tokenRenewerThreadTimeout, TimeUnit.MILLISECONDS);
                    } catch (TimeoutException e) {
                        // Handle TimeoutException, retry logic can be added here
                        System.out.println("Timeout occurred for key: " + key);
                    } catch (InterruptedException | ExecutionException ex) {
                        ex.printStackTrace();
                        // Handle other exceptions if needed
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        FutureTrackerExample1 example = new FutureTrackerExample1();
        RenewerPoolTracker renewerPoolTracker = example.new RenewerPoolTracker();
        Thread trackerThread = new Thread(renewerPoolTracker);
        trackerThread.start();
    }
}


8.3 hadoop官方提供的解决方法代码示例(trunk 分支)


package com.example.demo.futuretracker;

import java.util.concurrent.*;
/**
 * 优化点:修改数据结构,不使用 map 集合存储任务,改用 LinkedBlockingDeque 阻塞队列存储任务。
 *        在 while(true)方法中使用队列的 take 方法获取任务,take方法是阻塞式的(内部调用 await 方法),
 *        即在队列为空的时候会一直阻塞式的等待,但此过程不持有锁,不占用 CPU 的使用权(核心思想)
 *        当队列中有任务进入(有 put 操作),put 操作内部会调用 signal 方法发送信号给处于 await 状态的线程,
 *        使其被唤醒后再获取锁并正常执行。
 * 解决思路:使用了锁的等待和唤醒机制,更为灵活优雅。
 *
 */
public class FutureTrackerExample2 {
    private final LinkedBlockingDeque<DelegationTokenRenewerFuture> futures = new LinkedBlockingDeque();
    private final long tokenRenewerThreadTimeout = 60;

    private final class RenewerPoolTracker implements Runnable {
        @Override
        public void run() {
            while (true) {
                DelegationTokenRenewerFuture dtrf;
                try {
                    //队列为空时阻塞,释放锁,等待被唤醒
                    dtrf = futures.take();
                    Future future = dtrf.getFuture();
                    future.get(tokenRenewerThreadTimeout, TimeUnit.MILLISECONDS);
                } catch (TimeoutException e) {
                    // Handle TimeoutException, retry logic can be added here
                    System.out.println("Timeout occurred ");
                } catch (InterruptedException | ExecutionException ex) {
                    ex.printStackTrace();
                    // Handle other exceptions if needed
                }
            }
        }
    }

    public static class DelegationTokenRenewerFuture {
        private Future future;

        public DelegationTokenRenewerFuture() {
        }

        public DelegationTokenRenewerFuture(Future future) {
            this.future = future;
        }

        public Future getFuture() {
            return future;
        }

        public void setFuture(Future future) {
            this.future = future;
        }
    }

    public static void main(String[] args) {
        FutureTrackerExample2 example = new FutureTrackerExample2();
        RenewerPoolTracker renewerPoolTracker = example.new RenewerPoolTracker();
        Thread trackerThread = new Thread(renewerPoolTracker);
        trackerThread.start();
    }
}

标签:ResourceManager,100%,Hadoop,private,hadoop,RenewerPoolTracker,future,new,public
From: https://blog.51cto.com/simplelife/9161410

相关文章

  • Hadoop之mapreduce参数大全-1
    1.设置Map/Reduce任务允许使用的最大虚拟内存大小mapred.task.maxvmem是MapReduce的一个配置参数,用于指定每个Map/Reduce任务允许使用的最大虚拟内存大小(以字节为单位)。如果一个任务使用的虚拟内存超过了此参数指定的值,则任务会被认为是失败的,并且MapReduce集群会尝试重新分配任......
  • Hadoop(3.3.4)-HDFS操作
    ApacheHadoop3.3.4–Overview01.appendToFilehadoopfs-appendToFilelocalfile/user/hadoop/hadoopfilehadoopfs-appendToFilelocalfile1localfile2/user/hadoop/hadoopfilehadoopfs-appendToFilelocalfilehdfs://nn.example.com/hadoop/hadoopfilehadoop......
  • Hadoop之mapreduce参数大全-2
    26.指定在Reduce任务在shuffle阶段的网络重试之间的最大延迟时间mapreduce.reduce.shuffle.retry-delay.max.ms是ApacheHadoopMapReduce任务配置中的一个属性,用于指定在Reduce任务在shuffle阶段的网络重试之间的最大延迟时间(以毫秒为单位)。在MapReduce任务中,Reduce任务在shuff......
  • “华为杯”杭州电子科技大学2023新生编程大赛 1005
    树-HDU7406$xordist(i,j)=xordist(i,k)\oplusxordist(k,j)$在数轴和树上都是成立的那么原式变成$\sum_{i=l}^{r}xordist(i,k)\oplusxordist(k,j)$这里k指定为1号点就变成了一个很简单的拆位考虑贡献的问题了#include<bits/stdc++.h>usingnamespacestd;#de......
  • 【2024潇湘夜雨】WIN11_Pro_Dev_23612.1000软件选装纯净版1.06
    【系统简介】=============================================================1.本次更新母盘来自WIN11_Pro_Dev_23612.1000。2.增加部分优化方案,手工精简部分较多。3.OS版本号为23612.1000。精简系统只是为部分用户安装,个别要求高的去MSDN下。4.集成《DrvCeo-2.15.0.5》网卡版、运......
  • 【技术探讨】用户使用其他厂家433MHz无线模块时,购买样品OK,小批量100个就会出现偶尔无
    许多用户使用其他厂家的433M透传无线模块反馈这样的问题:前期购买几个样品测试,在无线信号覆盖半径内,收发包测试都很稳定,但是小批量购买100个模块收发就会出现无法收发的情况。这是什么原因呢?首先科普一下,无线电波,在同一个信道同一时刻只允许一个节点发射行为。433M的无线透传模块,没......
  • 初中英语优秀范文100篇-049Should We Help Strangers-我们应该帮助陌生人吗
    PDF格式公众号回复关键字:SHCZFW049记忆树1Recently,ourclasshadadiscussionaboutwhetherweshouldhelpstrangers.翻译最近,我们班进行了一次讨论,关于我们是否应该帮助陌生人。简化记忆陌生人句子结构1"Recently":这是一个副词,表示"最近",用来修饰谓语动作发......
  • H6911升压恒流芯片 2.5V启动 锂电池无频闪调光顺滑100W大功率
    H6911是一款外围电路简洁的宽调光比升压调光LED恒流驱动器,可适用于2.6-40V输入电压范围的LED恒流照明领域。H6911可以实现高精度的恒流效果,输出电流恒流精度≤±3%,电压工作范围为2.6-40V,可以轻松满足锂电池及中低压的应用需求,输出耐压仅由MOS耐压决定。PWM调光支持高辉应用,支持1K以......
  • 建投数据入选2023年亿欧信创100强
    近日,亿欧智库发布《2023信创产业新发展趋势报告及100强》,建投数据凭借产品迭代、方案成熟、服务升级、生态完整和经营增长等实力,入选2023信创产业100强。在本次活动中,亿欧智库从千家信创厂商中进行筛选,并基于信创厂商技术突破能力、产品矩阵能力、应用落地能力、生态构建能力等,通过......
  • Cisco Firepower 1000 Series FTD Software 7.2.0 & ASA Software 9.18.1
    作者主页:www.sysin.org面向小型办公室的企业级保护在企业发展的过程中为企业保驾护航。Firepower1000系列提供高性能、易用性、深入的可视性与可控性,可快速检测和阻止威胁。该系列在设计上优化了安全服务,而不会降低网络性能。Firepower1000型号对比Firepower1010桌面型:集成交......