问题背景
收到频繁的告警邮件,定时任务调度失败,查看xxl-job的执行器列表是空的,但是服务又显示健康。
查看历史任务执行记录发现执行器是依次递减,由于是线上服务,只能先重启,然后线程日志也没有,同时尝试访问服务的健康检查接口,发现健康检查接口访问不通,应该是服务已经挂了,但是因为服务配置的TCP健康检查,没鲸云没有检测出来服务异常(血淋淋的教训)。


总结问题现象:xxl-job的执行器列表为空,TCP检测正常,服务显示正常,但是http健康检查接口访问不了,服务其实处于挂掉状态。
初步排查过程
1、查看线上的APM,发现两个异常
堆内存会定期处于打满的状态 (被打满的都是 Eden Space----校长的定时任务计算任务很大,打满也是正常的,而且看了GC次数,young GC 和 old GC也没有太大异常)-----挂掉的时刻和正常情况的堆内存几乎是相同的规律,dump出线上的内存后,查看也没有什么问题,暂时排除是内存问题导致。
发现重启的服务线程池一直在缓慢的增长,不是很理解,正常的线程池不会一直处于增长的状态,而且增长的数量也很大。


2、进入终端,用arthas查看服务器线程状态
arthas 进入终端,执行thread命令。
确实发现很多的线程处于WATING状态,dump出线程堆栈,发现有200多个线程处于WATING状态。


3、arthas 查看WATING状态的线程堆栈
发现所有线程都处于下面的堆栈,看不出什么太多的线索,代码中查看是不是有什么地方设置了无限线程的线程池,发现也没有这么挫的操作。

张师傅注入线程的init方法, 发现是xxl-job的线程
[arthas@1]$ stack java.lang.Thread "<init>"

当时是怀疑xxl-job的线程泄露,想着如果是这个原因应该线程增长到一定数量之后就会挂掉,等了等,发现线程增长一定数量(接近400)后就不在增长了……
又看了下线上之前跑的比较正常的服务,发现线上的线程数也是在接近400的数量级上一直很平稳,服务也很健康,应该也不会是这样原因,没有思路,暂时先将TCP的健康检查换成HTTP的保证服务挂掉的时候能够第一时间重启(后边分析了下,xxl-job的线程增长会这么快,是因为,xxl-job内置的jetty服务器的默认线程池为256个线程)。
再次排查过程
1、同事发现测试环境定时任务也挂了,查看了下测试环境的内存和线程池,发现基本和线上环境的是一样的,没有什么太大的异常,不过好在测试环境的是挂掉的现场,应该线索更多一点。
2、既然内存和线程没有发现什么

博客讲述了Java线上定时任务频繁挂掉的问题,经过排查发现是由于log4j2异步打日志时,由于Disruptor Ringbuffer满且消费者处理不过来,导致死循环,CPU被打爆,服务挂掉。分析涉及线程状态、内存、日志配置,最终找到是log4j2与Kafka元数据更新时的死锁问题,并提出了解决方案。
1519

被折叠的 条评论
为什么被折叠?



