一、问题分类与排查思路
1.性能问题
表现:响应慢、CPU/内存使用率高、吞吐量下降
排查路径:
监控指标定位(CPU、内存、线程数、GC次数)
线程栈分析(jstack)
性能分析工具(Arthas、JProfiler)
2.稳定性问题
表现:服务宕机、OOM、频繁Full GC
排查路径:
日志分析(应用日志、GC日志)
堆转储分析(jmap、MAT)
依赖检查(数据库、Redis、MQ等)
3.数据问题
表现:数据不一致、脏数据、事务问题
排查路径:
数据追踪(业务日志、binlog)
事务分析(数据库锁、事务隔离级别)
代码逻辑审查
二、排查工具箱
基础工具
# 进程查看 jps -l ps -ef | grep java # 线程分析 jstack <pid> > thread.dump top -Hp <pid> # 查看线程CPU占用 # 内存分析 jmap -heap <pid> jmap -dump:live,format=b,file=heap.bin <pid> jstat -gcutil <pid> 1000 10 # GC统计 # 网络分析 netstat -antp | grep <port> ss -s # socket统计高级诊断工具
Arthas- 阿里巴巴开源诊断工具
# 安装启动 curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar # 常用命令 dashboard # 整体监控 thread # 查看线程 watch # 方法观测 trace # 方法调用链追踪 jad # 反编译类JProfiler/VisualVM- 图形化分析
Prometheus + Grafana- 监控告警
三、系统化排查流程
第一步:现象收集
# 1. 系统资源 top -c free -h df -h iostat -x 1 # 2. JVM信息 jinfo <pid> jcmd <pid> VM.flags # 3. 应用日志 tail -n 1000 app.log | grep ERROR tail -f app.log | grep -A 10 -B 5 "关键词"第二步:定位问题类型
# CPU高问题 # 1. 找到高CPU进程 top -c # 2. 找到高CPU线程(将PID转为16进制) top -Hp <pid> printf "%x\n" <tid> # 3. 分析线程栈 jstack <pid> | grep -A 10 <nid_hex> # 内存问题 # 1. 实时监控 jstat -gc <pid> 1000 # 2. 生成堆转储 jmap -dump:live,format=b,file=heap.hprof <pid> # 或使用jcmd(推荐) jcmd <pid> GC.heap_dump /tmp/heap.hprof第三步:深入分析
线程死锁排查
// 使用Arthas快速诊断 thread -b // 查找阻塞线程 thread --state BLOCKED // 查看阻塞状态线程 // 或使用jstack jstack <pid> | grep -A 20 "deadlock"内存泄漏排查
# 1. 分析堆转储 # 使用Eclipse Memory Analyzer (MAT) # 或jhat jhat heap.hprof # 访问 http://localhost:7000 # 2. 查看对象直方图 jmap -histo:live <pid> | head -20慢SQL排查
-- 开启慢查询日志 SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 2; -- 查看当前慢查询 SHOW PROCESSLIST; SHOW FULL PROCESSLIST; -- 使用EXPLAIN分析执行计划 EXPLAIN SELECT * FROM table WHERE ...四、常见问题场景及解决方案
场景1:CPU使用率100%
排查步骤:
top -c找到高CPU Java进程top -Hp <pid>找到高CPU线程jstack <pid> > thread.txt线程ID转16进制:
printf "%x\n" <tid>在thread.txt中搜索对应线程
分析代码逻辑(常见:死循环、大量计算、频繁GC)
场景2:内存泄漏OOM
排查步骤:
# 1. 添加JVM参数(提前预防) -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc.log # 2. 分析堆转储 # 使用MAT打开heap dump,查看: # - Dominator Tree(支配树) # - Leak Suspects(泄漏疑点) # - Histogram(对象直方图)场景3:频繁Full GC
现象:应用卡顿、响应时间长
# 分析GC日志 jstat -gcutil <pid> 1000 10 # 常见原因: # 1. 年轻代太小:-Xmn调整 # 2. 内存泄漏:分析堆转储 # 3. 大对象:检查代码中的大数组、大集合 # 4. System.gc()调用:禁止-XX:+DisableExplicitGC场景4:数据库连接池耗尽
// 监控连接池使用情况 // HikariCP HikariPoolMXBean pool = hikariDataSource.getHikariPoolMXBean(); System.out.println("Active: " + pool.getActiveConnections()); System.out.println("Idle: " + pool.getIdleConnections()); System.out.println("Total: " + pool.getTotalConnections()); // 排查方向: // 1. 慢SQL导致连接持有时间过长 // 2. 事务未及时提交 // 3. 连接泄漏(未关闭ResultSet/Statement/Connection)五、进阶排查技巧
1.使用Arthas进行动态诊断
# 监控方法调用 watch com.example.service.*Service * '{params,returnObj,throwExp}' -x 3 # 追踪调用链 trace com.example.service.*Service * -j # 热更新代码(紧急修复) jad --source-only com.example.ProblemClass > /tmp/ProblemClass.java # 修改代码后 mc /tmp/ProblemClass.java -d /tmp redefine /tmp/com/example/ProblemClass.class2.网络问题排查
# 连接数统计 netstat -an | awk '/^tcp/ {print $6}' | sort | uniq -c # 端口检查 nc -zv host port telnet host port # 抓包分析(谨慎使用) tcpdump -i any port 8080 -w capture.pcap3.分布式链路追踪
// 集成SkyWalking、Zipkin等 // 查看完整调用链路,定位慢在哪一环六、预防与最佳实践
1.监控体系建设
应用指标:QPS、RT、错误率
JVM指标:GC次数、堆内存、线程数
系统指标:CPU、内存、磁盘、网络
业务指标:关键业务流程监控
2.日志规范
// 结构化日志 logger.info("order_created", StructuredLog.create() .with("orderId", orderId) .with("amount", amount) .with("userId", userId) .with("costTime", costTime)); // 关键位置添加TraceID MDC.put("traceId", traceId);3.代码层面防护
// 超时控制 @Bean public RestTemplate restTemplate() { return new RestTemplateBuilder() .setConnectTimeout(Duration.ofSeconds(5)) .setReadTimeout(Duration.ofSeconds(10)) .build(); } // 熔断降级 @HystrixCommand(fallbackMethod = "fallbackMethod") public String riskyOperation() { // ... } // 限流 RateLimiter limiter = RateLimiter.create(100); // 100QPS4.应急预案
快速回滚脚本
服务降级开关
流量切分能力
线上诊断工具预装
七、总结
生产问题排查的核心思路:
先恢复,后定位:优先保障服务可用性
从外到内:网络 → 系统 → 应用 → 代码
工具熟练:掌握至少一种深度诊断工具
数据驱动:基于监控数据和日志分析
持续优化:将排查经验转化为监控告警和代码规范