线上故障如何快速排查?来看这套技巧大全( 三 )


(6)垃圾收集器总结

线上故障如何快速排查?来看这套技巧大全

文章插图
 
(7)实际场景中算法使用的组合
线上故障如何快速排查?来看这套技巧大全

文章插图
 
(8)GC日志格式
(a)监控内存的OOM场景
不要在线上使用jmap手动抓取内存快照 , 其一系统OOM时手工触发已经来不及 , 另外在生成dump文件时会占用系统内存资源 , 导致系统崩溃 。只需要在JVM启动参数中提取设置如下参数 , 一旦OOM触发会自动生成对应的文件 , 用MAT分析即可 。
# 内存OOM时 , 自动生成dump文件 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/如果Young GC比较频繁 , 5S内有打印一条 , 或者有Old GC的打印 , 代表内存设置过小或者有内存泄漏 , 此时需要抓取内存快照进行分享 。
(b)Young Gc日志
2020-09-23T01:45:05.487+0800: 126221.918: [GC (Allocation Failure) 2020-09-23T01:45:05.487+0800: 126221.918: [ParNew: 1750755K->2896K(1922432K), 0.0409026 secs] 1867906K->120367K(4019584K), 0.0412358 secs] [Times: user=0.13 sys=0.01, real=0.04 secs]
线上故障如何快速排查?来看这套技巧大全

文章插图
 
(c)Old GC日志
2020-10-27T20:27:57.733+0800: 639877.297: [Full GC (Heap Inspection Initiated GC) 2020-10-27T20:27:57.733+0800: 639877.297: [CMS: 165992K->120406K(524288K), 0.7776748 secs] 329034K->120406K(1004928K), [Metaspace: 178787K->178787K(1216512K)], 0.7787158 secs] [Times: user=0.71 sys=0.00, real=0.78 secs]
线上故障如何快速排查?来看这套技巧大全

文章插图
 
2.2 应用CPU过高2.2.1 发现问题一般情况下会有监控告警进行提示:
线上故障如何快速排查?来看这套技巧大全

文章插图
 
2.2.2 查找问题进程利用top查到占用cpu最高的进程pid为14 , 结果图如下:
线上故障如何快速排查?来看这套技巧大全

文章插图
 
2.2.3 查找问题线程利用 top -H -p 查看进程内占用cpu最高线程 , 从下图可知 , 问题线程主要是activeCpu Thread , 其pid为417 。
线上故障如何快速排查?来看这套技巧大全

文章插图
 
2.2.4 查询线程详细信息
  • 首先利用 printf "%x n" 将tid换为十六进制:xid 。
  • 再利用 jstack | grep nid=0x -A 10 查询线程信息(若进程无响应 , 则使用 jstack -f ) , 信息如下:

线上故障如何快速排查?来看这套技巧大全

文章插图
 
2.2.5 分析代码由上一步可知该问题是由 CpuThread.java 类引发的 , 故查询项目代码 , 获得如下信息:
线上故障如何快速排查?来看这套技巧大全

文章插图
 
2.2.6 获得结论根据代码和日志分析 , 可知是由于限制值max太大 , 致使线程长时间循环执行 , 从而导致问题出现 。
三 MySQL3.1 死锁3.1.1 问题出现最近线上随着流量变大 , 突然开始报如下异常 , 即发生了死锁问题:
Deadlock found when trying to get lock; try restarting transaction ;3.1.2 问题分析3.1.2.1 查询事务隔离级别利用 select @@tx_isolation 命令获取到数据库隔离级别信息:
线上故障如何快速排查?来看这套技巧大全

文章插图
 
3.1.2.2 查询数据库死锁日志利用 show engine innodb status 命令获取到如下死锁信息:
线上故障如何快速排查?来看这套技巧大全

文章插图
 

线上故障如何快速排查?来看这套技巧大全

文章插图
 
由上可知 , 是由于两个事物对这条记录同时持有S锁(共享锁)的情况下 , 再次尝试获取该条记录的X锁(排它锁) , 从而导致互相等待引发死锁 。
3.1.2.3 分析代码根据死锁日志的SQL语句 , 定位获取到如下伪代码逻辑:
@Transactional(rollbackFor = Exception.class)void saveOrUpdate(MeetingInfo info) {// insert ignore into table values (...)int result = mapper.insertIgnore(info);if (result>0) {return;}// update table set xx=xx where id = xxmapper.update(info);}3.1.2.4 获得结论分析获得产生问题的加锁时序如下 , 然后修改代码实现以解决该问题 。


推荐阅读