使用Jstack进行服务问题排查
最近公司服务遇到了完全没有排查头绪的CPU过载问题,导致服务变为接近不可用的状态或者直接宕机。在二老板(技术组长)指导下学会了使用Jstack进行服务的线程状态查询,通过这种方法来排查线程死锁或者死循环的问题,故此记录排查步骤。
步骤
0. 问题说明
服务突然无法访问或响应速度特别慢。
1. 通过top
与ps
指令配合查询服务状态与pid
通过top
指令进行服务状态查询,查询结果为核心的SpringBoot服务的CPU占用超过100%。记下此处的问题服务的pid。
可以通过C键来显示完整的服务启动命令,以此来判断启动的服务内容
或者记下top中问题服务的pid,通过
ps -ef | grep <pid>
的方式来查询服务
2. 确保没有新的网络请求
为了保证Jstack的日志不受其他内容影响,需要先关闭服务器开放的接口端口,确保没有新的网络请求。
公司目前所用服务器是阿里云的,所以这次使用的方式是在阿里云控制台安全组中添加 拒绝22以外的所有端口 的规则,该做法是否稳妥有待商榷。
可能也可以通过临时修改nginx配置等其他方法来阻断网络请求,有待实践。
3. 通过jstack
指令来获取当前的服务线程状态日志
通过
1 | jstack -l <pid> |
指令来输出当前的服务线程状态,或者通过
1 | jstack -l <pid> > <log-file-name> |
来输出到指定的日志文件中,方便排查。
4. 查找日志文件中关于业务逻辑服务的线程
在日志中查找业务相关代码,可以通过项目特定的包结构com.xxx
等来找到线程所执行的具体代码位置,例如:
1 | ...... |
其中出现的项目代码位置大部分情况下都不止一处,应从最后一项开始查看,梳理逻辑。
这样就可以看出,在代码执行到XXXServiceImpl.java:99时,产生了线程死锁或者死循环,应从这里排查项目问题。
之后就是研究逻辑错误等一般的项目错误修复流程。
日志内容可能特别多,需要耐心慢慢排查。
为什么不使用Arthas
本次讨论的问题场景为CPU过载,top查询结果中CPU占用超过了100%。这种情况下,若再启动一个Arthas对问题服务进行监控,会导致指令执行极其缓慢或成为导致服务器宕机的最后一根稻草。