生产环境CPU飙高问题原因
0. CPU上运行的是线程, 所以就是说有线程一直在忙碌,一直在运行
- 线程中有CAS一直获取锁失败,并不断的通过自旋重试,这是CAS的缺点,因此大量线程在自旋重试,会空耗CPU。比如代码中运用了AtmicXXX这些原子类 或 ConcurrentHashMap 或 乐观锁重试这些东西都可能导致CPU飙高
解决方案:使用这些原子类,或者乐观锁时要注意一下,并且自己写乐观锁自旋重试要注意配置重试次数 - 云服务器安装了Redis, 黑客利用6379端口注入挖矿程序,导致占用CPU资源
解决方案:尽量不要让Redis在外网访问,不要暴漏ip,并把端口号 或 ip设置访问权限,所以云服务器尽量买一家的 - 服务端接口被DDOS恶意攻击,当然要做大量的DDOS攻击,要花大量的钱,不是深仇大恨一般不会
解决方案:可以买高仿服务器,但是价格高。或者对接口做限流,图形验证码,ip黑名单等,对接口做限流可以防止服务器崩溃,但依然会把正常的良性请求也给拒绝了 - 代码出现了死循环打印,导致线程无法结束。
解决方案:要合理做一些退出循环的操作, 比如做一些循环次数限制,或者循环时间限制
Windows如何去排查CPU是什么原因飙高
- 打开任务管理器 ctrl + alt + del
- 看一下cpu百分比最高的对应哪个进程
Linux性能优化诊断pidstat+mpstat命令详解
mpstat(全局化查询命令,看总体):
- 全局查询命令: 直接【mpstat】就行
- 带参数更细化的查询【mpstat -P ALL 2 3】
- -P ALL: 表示查看所有CPU, 如果-P 1表示查看第二颗CPU, 最大是N-1
- 2: 表示每两秒刷新一下指标数据
- 3: 总共刷新3次,3次后就不刷新了
- 截图演示效果
- 参数说明(非顺序排列,前4个事核心参数,必须会看。):
- %usr: 用户态所使用 CPU时间的百分比,CPU使用率。(CPU在用户态真正参与工作了)
- %sys:内核态所使用 CPU时间的百分比,CPU使用率。(CPU在内核态真正参与工作了)
- %iowait: CPU 在等待 I/O 操作完成所消耗的时间,高表示可能 I/O 存在瓶颈。(注意:这里是等待IO,也就是说CPU并没有工作,是在空等IO操作完成。越大说明越有IO问题)
- %idle: CPU空闲且系统没有未完成的磁盘I/O请求的时间百分比; CPU使用率低,iowait高,idle低的话可能是等待IO, 则需要优化下IO相关代码,是否考虑使用零拷贝,缓存,合理设计数据库索引等优化方案
- %irq: 用于硬中断的 CPU 百分比。
- %soft: 用于软中断的 CPU 百分比。
- %steal: 虚拟机强制CPU 等待的时间百分比(基本很少关注)。
- %guest: 虚拟机占用CPU时间的百分比(基本很少关注)。
- %gnice: CPU运行niced guest虚拟机所花费的时间百分比(基本很少关注)。
pidstat(局部查询命令,看细节)
-
查看所有线程状况,直接输入命令【pidstat】即可, 一般使用【pidstat -u 2 3】 表示查看所有属性,每个2刷新一次,一共刷新3次
-
通常用【pidstat -u | sort -k 8 -r】 表示查看全部属性,并根据第8列倒序排列(sort -k 8 根据第8列排序,-r 表示倒序,第8列是CPU使用率)
-
常用命令:
- -u: 默认参数,显示各个进程的cpu统计,监控cpu, pidstat 和 pidstat -u -p ALL是等效的, 举例命令【pidstat -u 2 3】
- -r 显示各个进程的内存使用统计,监控内存,举例命令【pidstat -u | sort -k 8 -r】
- -d: 显示各个进程的IO情况,监控硬件, 举例命令【pidstat -d】
- -p: 指定进程号,比如【pidstat -p 5】, 这个5是进程号pid,不是第五个cpu。
- -w: 显示每个进程上下文切换情况,举例【pidstat -w】
- -t: 显示进程内部的线程使用情况【pidstat -t -p [pid] 查看指定进程的线程详情】
-
展示-u的样子
-
各参数说明:
- PID: 进程id
- %usr: 进程在用户态所使用 CPU时间的百分比,是CPU真实使用率
- %system: 进程在内核态所使用 CPU时间的百分比,是CPU真实使用率
- %guest: 进程在虚拟机占用cpu的百分比(基本很少关注)
- %wait: 进程等待cpu 的时间百分比, 进程处于就绪队列中的状态等待CPU调度运行的百分比, 不要和mpstat的iowait混淆了,%wait是等待CPU去处理的,已经是就绪态了。 而mpstat的iowait是指CPU要等待IO返回数据。
- %CPU: 进程占用cpu的百分比,和top命令一样 等于 用户态CPU+内核态 CPU,如果要区分cpu哪个态多则用pidstat,不包括 %wait, %wait是就绪态,还没消耗CPU呢。
- CPU: 处理进程的cpu编号
- Command: 当前进程对应的命令名字
-
-w展示的参数
7. 各参数详情
- UID: 不用关注
- PID: 进程ID
- cswch/s: CPU自愿的上下文切换: 意思就是,进程获取不了所需要的自愿,无法继续进行了,比如I / O瓶颈问题, 或内存不足等,会导致自愿上下文切换,就是并不是被时间片强制切换,而是由于资源不足而CPU自动切换的
- nvcswch/s: 非自愿的上下文切换: 意思就是,进程运行一切正常,但由于时间片不足了,被操作系统强行切换了。
- Command: 当前进程对应的命令名字
常用的组合命令(要记住)
- 命令: 【pidstat -wt 1】,表示查看具体进程里面的线程上下文切换信息,1表示并每秒刷新1次
- 命令: 【 pidstat -wt -p 4 1】, -p 4表示查看指定pid = 4的进程下的线程上下文切换信息,并每秒刷新1次
top命令查看具体线程下的代码层级
- 执行 【top -c】命令,查出CPU使用率高的进程PID
- 先看宏观,别着急进入线程级别
-
- 先看下cpu负载load average: xxxx, 这个是cpu的负载参数
-
- 再看下%Cpu这行,us = 用户态CPU使用率, sy = 内核态CPU使用率, wa = CPU等待时间io的时间(属于宏观)
-
- 如果load average特别高,wa也很高, 但是us + sy却比较低,那很有可能是cpu大部分都在等待io操作返回数据,而实际并没有工作。
-
- 否则如果us + sy比较高,那就说明cpu确实在做事情,那就要进一步进入线程级别看看,是什么地方让cpu这么忙碌
- 执行 【top -Hp PID】 得到该进程下的所有线程,以及线程ID
- 执行 【printf “%x\n” 线程ID】 得到16进制的线程ID
- 执行 【jstack -l PID > /tmp/log.txt】将堆栈信息打印到一个文件内
- 执行 【vim /tmp/log.txt】进入这个文件
- 进入文件后,按"“表示搜索,然后把第三步生成的16进制id复制到”" 后面然后回车找到目标位置,看看cpu信息,以及是不是自己写的代码
生产环境如何去排查CPU是什么原因飙高
- 服务器监控系统:比如阿里云CPU飙高的告警提示
- 运维先知道那台服务器节点CPU飙高,通知开发人员配合该服务器,进程中哪个线程导致cpu飙高
- 这些问题需要运维查,生产环境一般开发人员一定是碰不到的
- 或者通过第三方监控软件的平台查询。