项目背景:
大型内部管理项目
项目特点:
单个客户请求量很大,平均每个客户在登录过程中会产生大致70+左右的请求及一条长链接建立
(由于开发环境为内网环境,无法将排查过程的截图展示出来)
问题描述:
在测试过程中发现,服务正常的情况下,没有请求到达服务端。所有请求会有报错为网络超时。
重启可以让服务正常,但持续不了多久,上述情况依旧会出现。
请求链路为:
web -> ng -> admin管理台服务 -> 其他服务
排查过程:
1.排查nginx是否正常,通过查询nginx日志可以看出,请求正常转发。但服务端无响应日志
2.排查服务日志,经过查看发现最后卡住的线程号都比较大,说明没有线程被释放从而导致阻塞。在此处做了很多功夫,耽误了不少时间,比如修改最大线程,修改超时时间等。但最后发现只能减少问题出现的时间,并不能避免问题,说明本质问题不在此。但不代表如果遇到相同情况的同学可以忽略这步骤。
3.jstack 命令排查堆栈信息,在此操作之前,也查看了GC,但并没有发现问题,所以不做过多赘述。在排查堆栈信息的过程中,发现很多线程状态为WATTING,无限期等待,说明此部分线程,可能混杂着正常与非正常的线程。其中发现RUNNING状态的线程多为Redis相关线程。
4.修改redis连接超时时间等参数,来测试redis的链接是否出现问题,经测试未发现问题。
5.此时能确定问题的根本与redis有关,但不清楚具体哪些情况下会出现问题,从而继续排查服务日志,发现了关键点
"所有被阻塞的线程均与数据库连接相关!"
6.立刻想到了既用到Redis又用到了数据库连接的序列服务,返回堆栈信息确实发现了被阻塞的事务相关类
7.排查序列服务代码,发现均加了事务控制信息。进行并发模拟,发现在使用过程中,所写涉及事务代码优化部分会导致占用数据库连接,导致数据库连接池无法产生新的数据库连接。
至此,问题解决,优化了事务获取获取redis锁逻辑等相关逻辑