java诊断工具
陷入误区或是找不到方向时考虑
考虑“鸡”和“蛋”的问题
-
发现业务逻辑执行很慢且线程数增多的情况时
- 程序逻辑有问题或外部依赖慢,使得业务逻辑执行慢,在访问量不变的情况下需要更多的线程数来应对
- 有可能是请求量增大了,使得线程数增多,应用本身的 CPU 资源不足,再加上上下文切换问题导致处理变慢了
考虑通过分类寻找规律
分析问题需要根据调用拓扑来,不能想当然
考虑资源限制类问题
考虑资源相互影响
排查网络问题要考虑三个方面,到底是客户端问题,还是服务端问题,还是传输问题
快照类工具和趋势类工具需要结合使用
不要轻易怀疑监控
如果因为监控缺失等原因无法定位到根因的话,相同问题就有再出现的风险
- 做好日志、监控和快照补漏工作
- 做好实时报警
- 考虑做一套热备的方案
组件层面
排查组件所在主机是否有问题
排查组件进程基本情况,观察各种监控指标
查看组件的日志输出,特别是错误日志
进入组件控制台,使用一些命令查看其运作情况
主机层面
CPU
- 可以使用 top、vmstat、pidstat、ps 等工具排查
内存相关
- 可以使用 free、top、ps、vmstat、cachestat、sar 等工具
IO相关
- 可以使用 lsof、iostat、pidstat、sar、iotop、df、du 等工具
网络相关
- 可以使用 ifconfig、ip、nslookup、dig、ping、tcpdump、iptables 等工具
常见4个案例
JVM 参数配置问题
网络问题
内存问题
CPU 使用高的问题
-
使用Arthas分析高 CPU 问题
- 通过 dashboard + thread 命令基本可以在几秒钟内一键定位问题,找出消耗 CPU 最多的线程和方法栈
- 直接 jad 反编译相关代码,来确认根因
- 如果调用入参不明确的话,可以使用 watch 观察方法入参,并根据方法执行时间来过滤慢请求的入参
不同环境
开发环境
测试环境
- JDK 自带的 jvisualvm
- 阿里的Arthas,附加到远程的 JVM 进程排查问题
- 可以尝试去造一些场景让问题更容易出现
生产环境
- 生产环境权限管控严格,一般不允许调试工具从远程附加进程
- 生产环境出现问题要求以恢复为先,难以留出充足的时间去慢慢排查问题
生产环境
日志
- 确保错误、异常信息可以被完整地记录到文件日志中
- 确保生产上程序的日志级别是 INFO 以上
监控
-
需要开发和运维团队做好充足的监控
-
主机
-
网络
-
所有的中间件和存储都要做好监控
- 比如,著名的监控工具 Prometheus,就提供了大量的exporter来对接各种中间件和存储系统
-
应用层面
- 需要监控 JVM 进程的类加载、内存、GC、线程等常见指标
快照
- 应用进程在某一时刻的快照。通常情况下,我们会为生产环境的 Java 应用设置 -XX:+HeapDumpOnOutOfMemoryError 和 -XX:HeapDumpPath=…这 2 个 JVM 参数,用于在出现 OOM 时保留堆快照
CPU 使用高的问题
现场在
- 在 Linux 服务器上运行 top -Hp pid 命令,来查看进程中哪个线程 CPU 使用高;
- 输入大写的 P 将线程按照 CPU 使用率排序,并把明显占用 CPU 的线程 ID 转换为 16 进制
- 在 jstack 命令输出的线程栈中搜索这个线程 ID,定位出问题的线程当时的调用栈。
- 如果不能使用top命令,可以间隔固定秒数(比如 10 秒)运行一次 jstack 命令,采样几次后,对比采样得出哪些线程始终处于运行状态,分析出问题的线程
现场不在(排除法)
-
突发压力
-
GC
- 通过 JVM 监控 GC 相关指标、GC Log 进行确认
-
程序中死循环逻辑或不正常的处理流程
内存泄露或 OOM 的问题
堆转储后使用 MAT 分析
-
直方图
-
深堆浅堆
-
支配树界面
- 会按照对象保留的 Retained Heap 倒序直接列出占用内存最大的对象
-
线程视图
-
OQL
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=.堆转储配置
IO 相关的问题
除非是代码问题引起的资源不释放等问题,否则通常都不是由 Java 进程内部因素引发的
网络相关
可以先尝试使用 ping 等工具简单判断,如果不行再使用 tcpdump 或 Wireshark 来分析。