假如生产环境出现CPU占用过高,请谈谈你的分析思路和定位
记一次印象深刻的故障?
常见的cpu飙高原因:
1、CAS 自旋一直重试导致 cpu 飙高 没有控制自旋次数;
2、死循环
3、Redis 被注入挖矿程序,建议 Redis 端口不要能够被外网访问;
4、服务器被 DDOS 工具导致 cpu 飙高,可以通过限流、ip 黑名单、图形验证码防止机器模拟攻击等
5、不合理的使用线程。如:创建线程池的方式也是核心线程数、最大线程数是一样的,导致一些空闲的线程也得不到回收;这样会有很多无意义的资源消耗。
由此我们知道在发生这类问题其解决关键就是找到发生cpu飙升的进程 --> 通过进程找到占用率最高的线程 --> 通过该线程找到对应的业务逻辑从而优化代码解决。
1、使用top命令找出CPU占比最高的
2、ps -ef 或者 jps 进一步定位,得知是一个怎么样的后台程序出的问题
3、定位到具体线程或者代码
ps -mp 进程 -o THREAD,tid,time
参数解释
- -m:显示所有的线程
- -p:pid进程使用CPU的时间
- -o:该参数后是用户自定义格式
下图3929便是造成cpu过高的十进制线程id
4、将需要的线程ID转换为16进制格式(英文小写格式)
因为线程在内存中跑是16进制的,所以需要执行如下的命令把上面得到的十进制的线程id(3929)转换成16进制。当然也可以用计算器转换。
printf "%x\n" 有问题的线程ID #\n表示换行
十进制的3929转为十六进制为f59
5、jstack 进程ID | grep tid(16进制线程ID小写英文) -A60
这张图是之前截得,有点问题,线程id应该为上面的f59的,不是13ee的。
这样便可以精准定位到错误的地方。
6、总结
这里总结个解决问题的思路,当然有不同的解决方案。