线上的问题在通常有一些预警,比如CPU被打满,网络达到顶峰等等问题。或者用户的反馈,比如某某页面打不开,系统加载很慢,一直提示报错等等。
应急操作:
1 记录问题发生的情况
包括服务器的情况,Java虚拟机的一些情况,数据库的连接情况等等。
2 尽快让用户正常使用系统
常用的方法就是系统降级:
- 让出问题的服务先停掉。
- 代码回滚:往往问题都是在代码更新后出现的。
- 重启大法,要尽快的保证用户能正常使用。
线上问题异常及可能的原因
1 应用层面
应用层面的排查主要是CPU、load、内存以及网络
1.1 CPU
如果发现CPU占用率很高,这个时候就要考虑CPU跑满的原因:
1、FULL GC 频繁
2、有非常耗CPU的操作
通过一些命令将CPU占用最高的几个线程查看出来.
(1)通过ps -ef | grep java 或者 jps 找到pid
[root@iZj6ch2a1k9ok9a599lk5bZ ~]# ps -ef | grep java
root 307137 1 2 12:56 ? 00:03:59 java -jar -Xms512m -Xmx1024m -XX:MaxMetaspaceSize=128m -Dspring.profiles.active=prod /usr/local/fastcms/cms-1.0-SNAPSHOT.jar
root 312259 312064 0 15:11 pts/0 00:00:00 grep --color=auto java
[root@iZj6ch2a1k9ok9a599lk5bZ ~]# jps
312260 Jps
307137 cms-1.0-SNAPSHOT.jar
(2)top -Hp pid 找到使用CPU最高的线程
上面已经得到了pid是307137
[root@iZj6ch2a1k9ok9a599lk5bZ ~]# top -Hp 307137
top - 15:13:47 up 13 days, 16 min, 7 users, load average: 2.56, 2.45, 2.44
Threads: 42 total, 0 running, 42 sleeping, 0 stopped, 0 zombie
%Cpu(s): 11.0 us, 3.8 sy, 0.0 ni, 54.3 id, 29.4 wa, 0.7 hi, 0.8 si, 0.0 st
MiB Mem : 3591.0 total, 105.8 free, 2280.0 used, 1205.3 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 352.5 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
308128 root 20 0 3009752 986008 0 S 0.3 26.8 0:07.98 http-nio-8085-e
308132 root 20 0 3009752 986008 0 S 0.3 26.8 0:08.14 http-nio-8085-e
307137 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.01 java
307138 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.56 java
307139 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.91 GC Thread#0
307140 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.00 G1 Main Marker
307141 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.23 G1 Conc#0
307142 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.08 G1 Refine#0
307143 root 20 0 3009752 986008 0 S 0.0 26.8 0:02.16 G1 Service
307144 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.42 VM Thread
307145 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.00 Reference Handl
307146 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.11 Finalizer
307147 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.00 Signal Dispatch
307148 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.02 Service Thread
307149 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.14 Monitor Deflati
307150 root 20 0 3009752 986008 0 S 0.0 26.8 1:26.04 C2 CompilerThre
307151 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.41 C1 CompilerThre
307152 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.85 Sweeper thread
307153 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.00 Notification Th
307154 root 20 0 3009752 986008 0 S 0.0 26.8 0:03.64 VM Periodic Tas
307155 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.02 Common-Cleaner
307156 root 20 0 3009752 986008 0 S 0.0 26.8 0:01.01 GC Thread#1
308053 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.01 G1 Refine#1
308054 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.15 mysql-cj-abando
308055 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.18 Druid-Connectio
308056 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.04 Druid-Connectio
308057 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.65 Catalina-utilit
308058 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.65 Catalina-utilit
308059 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.05 container-0
308065 root 20 0 3009752 986008 0 S 0.0 26.8 0:39.64 scheduling-1
308123 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.79 http-nio-8085-e
308124 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.55 http-nio-8085-e
308125 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.30 http-nio-8085-e
308126 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.02 http-nio-8085-e
308127 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.92 http-nio-8085-e
308129 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.07 http-nio-8085-e
308130 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.05 http-nio-8085-e
308131 root 20 0 3009752 986008 0 S 0.0 26.8 0:08.44 http-nio-8085-e
308133 root 20 0 3009752 986008 0 S 0.0 26.8 0:01.36 http-nio-8085-P
308134 root 20 0 3009752 986008 0 S 0.0 26.8 0:01.61 http-nio-8085-A
308891 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.00 Java2D Disposer
310796 root 20 0 3009752 986008 0 S 0.0 26.8 0:00.00 Attach Listene
(3)printf '0x%x' tid 线程id转化为16进制
上面又二十多个线程吧,查看上面指定线程的16进制
[root@iZj6ch2a1k9ok9a599lk5bZ ~]# printf '0x%x' 308123
0x4b39b
(4)jstack pid |grep tid 找到线程堆栈
从上面获取的pid和tid得到线程堆栈信息
[root@iZj6ch2a1k9ok9a599lk5bZ ~]# jstack 307137 |grep 0x4b39b
"http-nio-8085-exec-1" #89 daemon prio=5 os_prio=0 cpu=8974.40ms elapsed=8449.87s tid=0x00007faed8439780 nid=0x4b39b waiting on condition [0x00007faead6fd000]
除此之外,也可以使用一些外部的检测工具比如arthas
1.2 Load
load指的是一段时间内CPU正在处理及等待的任务数,也是通过top命令:
load average: 0.14,0.21,0.35,分别表示1分钟、5分钟、15分钟内系统的平均负荷。
top - 15:29:40 up 13 days, 32 min, 6 users, load average: 1.98, 2.47, 2.51
Tasks: 142 total, 1 running, 141 sleeping, 0 stopped, 0 zombie
%Cpu(s): 5.9 us, 3.4 sy, 0.0 ni, 82.8 id, 7.4 wa, 0.3 hi, 0.2 si, 0.0 st
MiB Mem : 3591.0 total, 118.6 free, 2272.5 used, 1199.9 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 360.2 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1487 systemd+ 20 0 1838940 687972 0 S 17.3 18.7 597:22.07 mysqld
60 root 20 0 0 0 0 S 1.0 0.0 55:07.03 kswapd0
70757 root 10 -10 269616 35808 0 S 0.7 1.0 93:06.46 AliYunDunMonito
307137 root 20 0 3009752 986764 0 S 0.7 26.8 4:15.54 java
Load会有两种场景:
CPU高,Load高:先查CPU利用率的问题
CPU不高,Load高:大部分情况都是因为磁盘读写请求过多导致大量IO等待,可通过:
查看阻塞态线程堆栈
jstack -l 307137 | grep BLOCKED
排查流程如下:
1、查看当前jvm内存的参数配置:jmap -heap pid
2、查看gc情况:jstat -gcutil pid
3、内存dump:jmap -dump:format=b,file=/tmp/dump.dat pid 这个命令在线上慎用,会导致系统变慢
4、内存分析工具分析
1.3 网络
出现网络问题的现象主要有两点:
1、http链接无法建立,有大量close_wait的tcp连接
2、tcp重传率高
关于网络问题,我在上家公司刚好遇到过,大量的等待tcp连接导致系统濒临宕机,后来发现是网络带宽500M变成了200M的问题。
2 数据库层面
2.1 CPU打满
数据库服务器的cpu被打满,原因可能是:
1、大数据量查询没有走索引,导致慢sql的出现
2、sql中存在各种导致索引失效的操作
问题解决方式:
通过运维工具(比如rds)找到sql执行时间最长的top10,通过explain查看sql执行是否走了索引,然后加索引优化。
2.2 网络流量飙升
原因可能是:
1、sql没有设置limit导致全部数据返回
2、sql的请求数量快速增加
解决方式:
1、在搜索代码中务必加上limit
2、运维工具查看异常时间段的sql执行情况
2.3 系统资源正常,sql一直阻塞
原因可能是:
1、一些sql操作导致锁表
解决方式:
1、通过数据库监控工具查找执行时间长的sql
2、将执行时间长的sql直接kill掉
3 总体的问题排查流程
1 及时收集信息
问题的故障点是很重要的,如果不清楚问题发生的原因,那就说明下次依旧可能发生,因此要将故障信息尽快收集起来,同时做好应用的监控。
2 定位原因
问题发生百分之95的原因是近期做了变更,思考近期变更的地方:
1、代码是否有更新
2、数据库是否有变更
3、网络是否做了切换
4、其他应用是否会影响你的应用
5、是否有流量突然变大的情况
同时收集日志、通过工具辅助定位原因,常用的工具有arthas
3 快速响应
在尽可能快的时间里将系统还原:
1、如果是代码更新导致,回滚代码
2、如果是数据库变更导致,切换回来
3、如果是网络做了调整,联系网管
4、如果是其他应用的影响,联系其他应用降级
5、如果是流量突然增大,限流
6、实在不知道怎么办,重启
4 Java应用内存配置及使用情况查看
[root@iZj6ch2a1k9ok9a599lk5bZ ~]# jhsdb jmap --pid 405365 --heap
Attaching to process ID 405365, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 17.0.7+8-LTS-224
using thread-local object allocation.
Garbage-First (G1) GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 1363144 (1.2999954223632812MB)
MaxNewSize = 643825664 (614.0MB)
OldSize = 5452592 (5.1999969482421875MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 22020096 (21.0MB)
CompressedClassSpaceSize = 109051904 (104.0MB)
MaxMetaspaceSize = 134217728 (128.0MB)
G1HeapRegionSize = 1048576 (1.0MB)
Heap Usage:
G1 Heap:
regions = 1024
capacity = 1073741824 (1024.0MB)
used = 258973696 (246.9765625MB)
free = 814768128 (777.0234375MB)
24.118804931640625% used
G1 Young Generation:
Eden Space:
regions = 168
capacity = 316669952 (302.0MB)
used = 176160768 (168.0MB)
free = 140509184 (134.0MB)
55.629139072847686% used
Survivor Space:
regions = 21
capacity = 22020096 (21.0MB)
used = 22020096 (21.0MB)
free = 0 (0.0MB)
100.0% used
G1 Old Generation:
regions = 59
capacity = 198180864 (189.0MB)
used = 60792832 (57.9765625MB)
free = 137388032 (131.0234375MB)
30.675429894179896% used
说明
堆配置:
MaxHeapSize
: 堆的最大大小为1024.0MB。NewSize
: 新生代的初始大小为1.3MB。MaxNewSize
: 新生代的最大大小为614.0MB。OldSize
: 老年代的大小为5.2MB。MetaspaceSize
: 元空间的大小为21.0MB。CompressedClassSpaceSize
: 压缩类空间的大小为104.0MB。MaxMetaspaceSize
: 最大元空间大小为128.0MB。
堆使用情况:
-
G1 Heap:
capacity
: 堆的总容量为1024.0MB。used
: 已使用的堆容量为247.0MB。free
: 堆的剩余空间为777.0MB。24.1%
的堆被使用。
-
G1 Young Generation:
- Eden Space:
capacity
: Eden空间的总容量为302.0MB。used
: 已使用的Eden空间为168.0MB。free
: Eden空间的剩余空间为134.0MB。55.6%
的Eden空间被使用。
- Survivor Space:
capacity
: Survivor空间的总容量为21.0MB。used
: Survivor空间已经被完全使用,占用了21.0MB。free
: Survivor空间没有剩余空间。
100.0%
的Survivor空间被使用。
- Eden Space:
-
G1 Old Generation:
capacity
: 老年代的总容量为189.0MB。used
: 老年代已使用的容量为58.0MB。free
: 老年代的剩余空间为131.0MB。30.7%
的老年代被使用。