web服务无响应问题排查记录
现象描述
线上服务接口全部无响应,不返回任何数据
查看GC,发现存在大量的fullGC:
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
512.0 6656.0 0.0 0.0 915456.0 18344.4 2091008.0 75385.7 128704.0 121019.9 15104.0 13831.6 90276 3010.944 38233 39143.272 42154.216
查看堆内存使用情况正常:
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 4294967296 (4096.0MB)
NewSize = 357564416 (341.0MB)
MaxNewSize = 1431306240 (1365.0MB)
OldSize = 716177408 (683.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 937426944 (894.0MB)
used = 18784656 (17.914443969726562MB)
free = 918642288 (876.0855560302734MB)
2.0038527930342913% used
From Space:
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
To Space:
capacity = 6815744 (6.5MB)
used = 0 (0.0MB)
free = 6815744 (6.5MB)
0.0% used
PS Old Generation
capacity = 2141192192 (2042.0MB)
used = 77194984 (73.6188735961914MB)
free = 2063997208 (1968.3811264038086MB)
3.6052337706264157% used
日志中存在heap out of memory的错误,但线程任务正常执行。
jstack查看线程状态也只正常,没有大量处于Block状态的线程。
通过命令查看tcp队列情况:
ss -tln
显示tcp的接收队列始终没有变化,也就是web应用没有消费队列中的连接。
此处奇怪的现象就是jvm的线程任务正常执行,却不响应http请求。
原因猜测
tomcat使用nio处理http请求,在写nio代码时一个经典的模型就是while循环中的接收新事件,并提交给线程池处理事件。猜测这个while循环因为heap out memory异常而退出,导致tomcat无法接收请求。
验证
观察正常启动的web影响线程情况:

线上服务的jstack中不存在Acceptor线程,说明已经退出,因此http请求不会响应。
修改方案
此次服务未响应的根本原因是heap out of memory异常,GC日志中存在大量的fullGC,但稳定后堆内存的占用正常,说明可能短时间内存在大量的大对象导致的堆溢出。因此解决方案为增加新生代的大小,避免大对象分配到老年代中。
tomcat源码解析
//TODO

浙公网安备 33010602011771号