线上CPU100%?看看这篇是怎么排查的!
前言
作为后端开发工程师,当收到线上服务器CPU负载过高告警时,你会这么做?重启服务,忽略告警?不过在我看来一个合格的工程师是一定要定位到具体问题所在的,从而 fix 它。下面记录一下线上服务器 CPU 负载过高排查过程,把排查流程理清楚,以后遇到问题将会迅速定位到问题所在,快速解决。
什么样的场景会导致线上CPU负载过高?
代码层面常见的场景有:
- 程序陷入死循环,不停地消耗CPU
- 线程死锁,线程相互等待,导致假死状态,不停地消耗CPU
程序死循环场景
这里使用 JAVA 简单模拟程序死循环带来的系统高负载情况,代码如下:
1/**
2 * @program: easywits
3 * @description: 并发下的 HashMap 测试....
4 * @author: zhangshaolin
5 * @create: 2018-12-19 15:27
6 **/
7public class HashMapMultiThread {
8
9 static Map<String, String> map = new HashMap<>();
10
11 public static class AddThread implements Runnable {
12
13 int start = 0;
14 public AddThread(int start) {
15 this.start = start;
16 }
17 @Override
18 public void run() {
19 //死循环,模拟CPU占用过高场景
20 while (true) {
21 for (int i = start; i < 100000; i += 4) {
22 map.put(Integer.toString(i), Integer.toBinaryString(i));
23 }
24 }
25 }
26 public static void main(String[] args) throws InterruptedException {
27 //线程并发对 HashMap 进行 put 操作 如果一切正常,则得到 map.size() 为100000
28
29 //可能的结果:
30 //1. 程序正常,结果为100000
31 //2. 程序正常,结果小于100000
32 Thread thread1 = new Thread(new AddThread(0), "myTask-1");
33 Thread thread2 = new Thread(new AddThread(1), "myTask-2");
34 Thread thread3 = new Thread(new AddThread(2), "myTask-3");
35 Thread thread4 = new Thread(new AddThread(3), "myTask-4");
36 thread1.start();
37 thread2.start();
38 thread3.start();
39 thread4.start();
40 thread1.join();
41 thread2.join();
42 thread3.join();
43 thread4.join();
44 System.out.println(map.size());
45 }
46 }
47}
线程死锁场景
同样使用 JAVA 程序简单模拟线程死锁场景,代码如下:
1/**
2 * @program: easywits
3 * @description: 死锁 demo ....
4 * 1.两个线程里面分别持有两个Object对象:lock1和lock2。这两个lock作为同步代码块的锁;
5 * 2.线程1的run()方法中同步代码块先获取lock1的对象锁,Thread.sleep(xxx),时间不需要太多,50毫秒差不多了,然后接着获取lock2的对象锁。
6 * 这么做主要是为了防止线程1启动一下子就连续获得了lock1和lock2两个对象的对象锁
7 * 3.线程2的run)(方法中同步代码块先获取lock2的对象锁,接着获取lock1的对象锁,当然这时lock1的对象锁已经被线程1锁持有,线程2肯定是要等待线程1释放lock1的对象锁的
8 * <p>
9 * 线程1″睡觉”睡完,线程2已经获取了lock2的对象锁了,线程1此时尝试获取lock2的对象锁,便被阻塞,此时一个死锁就形成了。
10 * @author: zhangshaolin
11 * @create: 2018-12-20 11:33
12 **/
13public class DeadLock {
14
15 static Object lock1 = new Object();
16 static Object lock2 = new Object();
17
18 public static class Task1 implements Runnable {
19
20 @Override
21 public void run() {
22 synchronized (lock1) {
23 System.out.println(Thread.currentThread().getName() + " 获得了第一把锁!!");
24
25 try {
26 Thread.sleep(50);
27 } catch (InterruptedException e) {
28 e.printStackTrace();
29 }
30
31 synchronized (lock2) {
32 System.out.println(Thread.currentThread().getName() + " 获得了第二把锁!!");
33 }
34 }
35 }
36 }
37
38 public static class Task2 implements Runnable {
39
40 @Override
41 public void run() {
42 synchronized (lock2) {
43 System.out.println(Thread.currentThread().getName() + " 获得了第二把锁!!");
44
45 synchronized (lock1) {
46 System.out.println(Thread.currentThread().getName() + " 获得了第一把锁!!");
47 }
48 }
49 }
50 }
51
52 public static void main(String[] args) throws InterruptedException {
53 Thread thread1 = new Thread(new Task1(), "task-1");
54 Thread thread2 = new Thread(new Task2(), "task-2");
55 thread1.start();
56 thread2.start();
57
58 thread1.join();
59 thread2.join();
60 System.out.println(Thread.currentThread().getName() + " 执行结束!");
61 }
62}
以上两种场景代码执行后,不出意外,系统CPU负载将会飙升,我的机器,4核CPU已经明显感觉到卡顿了,所以线上应该杜绝出现死循环代码。。
使用`top` 命令监控当前系统负载情况
执行第一种场景测试代码。
在 linux
命令行键入 top
指令后,就开始实时监控当前系统的负载信息,监控到的负载信息如下图所示:
从图中的监控信息可以快速大致的了解到,PID
为17499
的进程CPU负载高达328+%
,是一个 JAVA
程序。简单介绍下监控信息如下:
- PID:进程的ID
- USER:进程所有者
- PR:进程的优先级别,越小越优先被执行
- VIRT:进程占用的虚拟内存
- RES:进程占用的物理内存
- SHR:进程使用的共享内存
- S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负
- %CPU:进程占用CPU的使用率
- %MEM:进程使用的物理内存和总内存的百分比
- TIME+:该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值
在监控页面下 按键盘数字 1
可以看到每个CPU的负载情况,如下图:
可以看到开了四个线程,无限循环之后,我的机器中四个核心CPU,每颗负载接近百分百。
使用 `top` 命令监控进程中负载过高的线程
top -H -p pid
: 查看指定进程中每个线程的资源占用情况(每条线程占用CPU时间的百分比),监控结果如下图:
以上监控指令输出的指标针对的是某个进程中的线程,从图中看可以快速得出结论:四个 JAVA
线程CPU负载极高,线程ID分别为:17532
,17535
,17533
,17534
,注意这里打印出来的线程ID为十进制的哦!
根据`进程pid`&&`线程id`查看线程堆栈信息
jstack pid
:查看指定进程中线程的堆栈信息,这个命令最终会打印出指定进程的线程堆栈信息,而实际线上情况发生时,我们应当把快速把堆栈信息输出到日志文本中,保留日志信息,然后迅速先重启服务,达到临时缓解服务器压力的目的。jstack 17499 > ./threadDump.log
:将线程堆栈信息输出到当前目录下的 threadDump.log 文件。
注意:jstack 打印出的线程id号为十六进制,而 top 命令中打印出来的线程号为十进制,需要进行转换后,定位指定线程的堆栈信息
这里分析日志文件后,过滤出四个线程堆栈信息如下图:
从这四个线程执行的堆栈信息,很明显的看出:导致CPU飙升的程序正在执行 HashMap 的 put 操作。
友情提示:测试代码最好不要在公司的线上环境做测试哦!
更多原创文章会在公众号第一时间推送,欢迎扫码关注 张少林同学
线上CPU100%?看看这篇是怎么排查的!的更多相关文章
- 一次性搞清楚线上CPU100%,频繁FullGC排查套路
“ 处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及 Full GC 次数过多的问题. 当然,这些问题最终导致的直观现象就是系统运行缓慢,并且有大量的报警. 本文主要针对系统 ...
- 【原创】谈谈线上CPU100%排查套路
引言 不知道在大家面试中,有没有遇到这个问题 生产服务器上部署了几个java程序,突然出现了CPU100%的异常告警,你如何定位出问题呢? 这个问题分为两版回答! 高调版 对不起,我是做研发的,这个问 ...
- 线上CPU100%排查
生产服务器上部署了几个java程序,突然出现了CPU100%的异常告警,你如何定位出问题? 这个问题分为两版回答!高调版对不起,我是做研发的,这个问题在生产上是不可能遇见的!因为研发是不可能直接操作生 ...
- 谈谈线上CPU100%排查套路
知识点总结 ---------------------------------------------------------------------------------------------- ...
- 告诉你如何回答"线上CPU100%排查"面试问题
不知道在大家面试中,有没有遇到这个问题: 生产服务器上部署了几个java程序,突然出现了CPU100%的异常告警,你如何定位出问题呢? 这个问题分为两版回答!高调版对不起,我是做研发的,这个问题在生产 ...
- 性能分析 | 线上CPU100%排查
不知道在大家面试中,有没有遇到这个问题: 生产服务器上部署了几个java程序,突然出现了CPU100%的异常告警,你如何定位出问题呢? 这个问题分为两版回答! 高调版 对不起,我是做研发的,这个问题在 ...
- 线上 CPU100% 排查方案
问题:生产服务器上部署了几个java程序,突然出现了CPU100%的异常告警,你如何定位出问题呢? 下面给出两种系统下的排查步骤,都是一模一样的,只是命令稍有区别! 查消耗cpu最高的进程PID 根据 ...
- 线上cpu100%问题快速定位
问题描述:服务器上部署了多个tomcat,即垂直切分的Web站点,记忆多个Java微服务,突然收到运维的cpu异常告警. 步骤一:找到最耗cpu的进程 工具:top 方法: 执行top -c,显示进程 ...
- 如何回答“线上CPU100%排查”面试问题
案例: public class App { public static void main( String[] args ) { int a = 0; while (a < 100) { a ...
随机推荐
- c# ftp 上传文件 与 下载文件
接着上一篇说. 上一篇说了根据配置文件获取路径,并判断路径在服务器中是否存在.如果不存在则在服务器中建立一个. 然后就是往路径下面传输文件了.. 代码: //连接ftp private void Co ...
- Git,GitHub以及GitLab的区别
Git - 版本控制工具 Github - 一个网站,提供给用户空间创建git仓储,保存用户的一些数据文档或者代码等 GitLab - 基于Git的项目管理软件 Git分布式版本控制系统 Git是一款 ...
- spring+springmvc+mybatis+redis 实现两重数据缓存
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http:// ...
- 黑客攻击 UVa11825
http://www.cnblogs.com/acm-bingzi/p/3272898.html Hackers’ Crackdown Miracle Corporations has a numbe ...
- Mcrosoft中间语言的主要特征
Mcrosoft中间语言显然在.NET FrameWork中起着非常重要的作用.现在讨论一下IL(Intermideate Language)的主要特征.因为面向.NET的所有语言在逻辑上都需要支持I ...
- console对象的理解
console对象代表浏览器的JS控制台,虽然不是标准,但已经成为事实的标准 console对象的作用 a.显示代码运行错误信息 b.提供一个命令行接口,用来与网页互动 console对象拥有很多方法 ...
- 2015-08-13T17:39:15
ACTION里 Date upateTime; 有setter getter 页面字符串 是'2015-08-13T17:39:15' 该字符串可以直接映射成Date .
- web_custom_request函数详解【摘抄】
本次摘抄自:http://www.cnblogs.com/yezhaohui/p/3280239.html web_custom_request()函数是一个可以用于自定义http请求的“万能”函数, ...
- 等等,你可能误解nodejs了–通俗的概括nodejs的真相
最近刚把产品从cpp平台迁移到nodejs平台了. 很多以前关于nodejs的观念被颠覆了. 这里分享出来, 欢迎大家批评指正. "nodejs是做服务器端开发的, 它一定和web相关,几 ...
- 利用html5 postMessage接口跨域设置iframe大小
<!doctype html> <html> <head> <title>Document A</title> <meta chars ...