记一次Java线程堆栈分析
最新某系统经常出现无法登录,不能响应请求的情况。一开始找上我的时候,他们已经通过重启恢复了,然后让我查原因。我表示一脸懵逼,啥都没有就让我解决了,最起码得让我有东西分析吧。还好这个问题经常发生,于是就在一次故障发生的时候。
我使用jps
查到进程pid
,然后用jstack
将堆栈信息保存到一个文件里,然后就用上了我不知道啥时候收藏的网站fastThread,将文件上传上去。
嚯,这么多线程再WAITING
状态。点进去一个看看。
大多数线程的堆栈信息都跟上面差不多,都是在等从Druid数据库连接池等连接。
所以,原因就是数据库连接不够用了。然后我看了一眼数据库连接池的配置。
|
|
以我对这个系统的了解,这个配置完全够了。
于是,我打开了druid
的监控。
|
|
监控页面的部分功能需要设置这个。
|
|
果然,removeAbandoned
设置为true
之后就有地方出现问题了,抛出了connection holder is null
的异常错误。
这说明,有地方长时间占用数据库连接了,由于超时回收,导致事务提交的时候出现问题。找到出错的代码后发现是因为定时任务的所有操作都在一个事务里,一个定时任务几十分钟
。其实,这个定时任务完全没必要加一个这样的大粒度事务,它的大多数操作都不必与数据库交互。所以,只要把事务粒度控制好了问题就解决了。
另外,还有一个原因是下面这个配置并不会生效。我其实挺不理解的,Spring Boot的文档写得很清楚了,为什么还有人把这些配置弄错了,而且还不验证有没有生效。
|
|
因为系统用的Druid,所以正确的配置
是下面这样的
|
|