在Java线上环境中排查故障需要系统化的方法和合适的工具,以下是详细的排查步骤及常用工具:
快速确认问题现象
-
明确症状:确认是CPU飙升、内存泄漏、线程阻塞、响应超时,还是频繁Full GC。
-
查看监控:使用Prometheus、Grafana、Zabbix等工具查看系统指标(CPU、内存、线程、GC次数、请求量等)。
-
检查日志:通过ELK(Elasticsearch、Logstash、Kibana)或分布式日志系统搜索错误日志(如
ERROR
、Exception
)。
1. CPU占用过高
-
定位高CPU线程:
jps -l # 查看java 进程 获取pid top -H -p <pid> # 查看进程内各线程CPU占用 printf "%x\n" <tid> # 将线程ID转为16进制(用于jstack分析) jstack <pid> > thread.txt
-
在
thread.txt
中搜索nid=0x<16进制线程ID>
,查看线程堆栈。
-
-
工具辅助:
-
Arthas:使用
thread -n 3
查看最忙的3个线程。 -
Async-Profiler:生成火焰图定位热点代码。
-
2. 内存泄漏/OOM
-
查看内存分布:
jmap -heap <pid> # 堆内存概况 jstat -gcutil <pid> # GC统计(关注老年代占用)
-
导出堆快照:
jmap -dump:live,format=b,file=heap.hprof <pid>
-
使用 Eclipse MAT 或 VisualVM 分析
heap.hprof
,查找Retained Heap
最大的对象。
-
-
Arthas内存分析:
dashboard # 实时内存监控 heapdump --live /tmp/heap.hprof # 导出堆快照
3. 线程阻塞/死锁
-
查看线程状态:
jstack <pid> > thread.txt
-
搜索
BLOCKED
、WAITING
状态的线程,分析代码锁竞争。
-
-
Arthas快速诊断:
thread -b # 直接定位死锁线程 thread --state BLOCKED # 查看阻塞线程
4. 响应缓慢
-
链路分析:
-
使用分布式追踪工具(SkyWalking、Zipkin)查看请求链路耗时。
-
-
数据库慢查询:
-
开启MySQL慢查询日志,或使用Arthas的
watch
命令监控SQL执行时间:watch com.mysql.jdbc.ConnectionImpl executeQuery "{params, returnObj}" -x 3
-
-
代码级瓶颈:
-
Arthas Profiling:
profiler start # 开始采样 profiler stop --format html # 生成火焰图
-
5. 频繁Full GC
-
检查GC日志:
-
JVM参数添加
-Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps
。 -
使用 GCViewer 或 GCEasy 分析GC日志,观察老年代回收效率。
-
-
常见原因:
-
内存泄漏(通过堆快照分析)。
-
JVM参数不合理(如堆大小、Survivor区比例)。
-
6. 网络与I/O问题
-
连接池耗尽:
-
检查数据库连接池(如HikariCP)配置,使用
jstack
查看等待连接的线程。
-
-
网络延迟:
-
使用
tcpdump
或Wireshark抓包分析。 -
Arthas网络诊断:
trace java.net.SocketInputStream socketRead
-
辅助工具清单
工具 | 用途 |
---|---|
jstack | 线程堆栈分析(死锁、阻塞) |
jmap | 内存快照导出 |
Arthas | 在线诊断(动态反编译、监控方法执行) |
VisualVM | 本地JVM监控与堆分析 |
Eclipse MAT | 内存泄漏分析 |
Async-Profiler | 低开销火焰图生成 |
预防与最佳实践
-
提前埋点:关键方法添加Trace ID,方便日志追踪。
-
灰度发布:逐步验证新版本,减少全局风险。
-
压测与预案:定期全链路压测,准备限流、降级策略。
通过以上步骤,结合日志、监控和工具,可以高效定位并解决大多数Java线上故障。