线上应用故障排查思路

# 线上应用故障排查思路

线上应用故障,通常可以分为四个部分入手排查,也可能故障不是一方面到导致,所以我们根据问题,一个个去切入排查。

首先登录机器,使用 top 命令观察机器的整体情况,显示如下

top命令

# CPU 使用异常

当应用出现响应慢时,一般可能是CPU使用异常,例如上下文频繁切换、频繁GC、死循环等。

# 线程死循环

使用top命令查看机器 CPU 使用情况,如果出现单个进程CPU占用过高,则进行下一步操作,如果未发现CPU占用过高的情况则估计非死循环导致CPU使用异常。

使用 top命令后按H键后将会按照CPU使用情况从高到低排序,找到占用CPU较高的进程对应的PID ,如下图占用最高的PID为3629272

image-20230201145217113

使用命令打印该进程下占用CPU较高的线程信息

top -H -p PID
1

输入后得到该进程下占用CPU较多的线程,可以看见PID为3629289

image-20230201145658920

**注意:**在线程堆文件中,是 16 进制表示的,所以要将该 PID 转为 16 进制

printf '%x\n' 3629289
1

转换结果为 3760e9

接着可以直接在该进程的线程运行信息中查找该 ID,其中PID为目标进程的PID,nid为线程PID转换后成16 进制后的数字

jstack PID | grep 'nid' -C 10
1

不直接查看也可以先导出该进程的线程信息快照,然后分析该文件,导出时加上-l参数会增加显示关于锁的附加信息,用于检查线程死锁

jstack -l 3629272 >> TestDeadCycle.jstack.log
1

在文件中查找的结果,显示正在运行的代码位置在TestDeadCycle类第6行,我们可以去观察这附近的代码,继续排查问题。

image-20230201151514572

对于生成了线程快照文件,可以分析文件得到线程的状态,如果大量线程处于WAITING或者TIMED_WAITING或者BLOCKED那肯定是有问题的。

统计线程状态命令

cat TestDeadCycle.jstack.log | grep "java.lang.Thread.State" | sort -nr | uniq -c
1

image-20230201152957306

# 频繁 GC 导致 CPU 过高

频繁的GC会带来较大的性能损失,也会消耗大量的CPU资源,查看目标线程的 GC,采样间隔为 1000ms 命令如下

jstat -gc PID 1000
1

image-20230201154648335

# 频繁上下文切换

频繁切换上下文,不一定会导致CPU使用率过高,但是会导致CPU执行代码的时间变少,导致程序运行效率降低,系统响应速度变慢。

使用vmstat命令查看上下文切换信息,其中cs(context switch)列表示上下文切换的次数。

vmstat PID
1
root@VM-20-5-ubuntu:~# vmstat 3629272
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 164560  90072 1453320    0    0     1    16    1    2  0  0 99  0  0

1
2
3
4
5

# 磁盘使用异常

# 内存使用异常

# 网络使用异常