Java 开发

线上定时任务全部罢工

言七墨 · 12月1日 · 2019年 · 659次已读

场景描述

针对某块业务有两个 JOB,一个是全局处理的 JOB(每天0点执行),一个是部分处理的 JOB(每5分钟执行一次)。当晚上线时,由于已经过了0点,也就没有看这个定时任务是否正常执行(查看日志,其它定时任务都在正常执行)。隔天早上,看日志时,发现所有的定时任务全部罢工了,也没有任何报错信息。然后汇报组长问题,组长重启服务后又全部正常了(重启真是万能药呀)。后又看了看测试环境的定时任务是否正常,结果也全部罢工了,很奇怪,当时自测时,每个定时任务都是没问题的(后文揭晓)。但是具体什么原因导致的,当时真的不清楚。

猜测原因

  • cron 的规则错误?经过网上验证,没问题。
  • 是不是不应该使用 cron 的方式?请看链接,网上说的。

出现转机

组长发了一组线上的慢查询,在里面发现了这个全局 JOB 中的慢查询语句,这个慢查询语句执行了 2000 多遍,花了 2 个半小时的时间(从 0 点到 2 点半),如下图:

罢工原因 & 反思

执行了 2000 多遍的慢查询语句,无异于在定时任务里放了个“死循环”。执行这个 JOB 耗费了 2 个半小时,那这个 JOB 就占用线程池的资源 2 个半小时,而定时任务的线程池中只有一个有效的线程资源,同时这些定时任务又存在于定时队列中,这就导致线程池长时间不能响应后续的 JOB,最终这个唯一有效的线程出现了“假死”的现象,这就导致了定时任务集体罢工的现象。

而测试环境在测试时没有重现是因为测试环境的数据量不是很大,慢查询也不会很慢,而线上数据量就非常庞大,慢查询就真的慢了,也就导致在测试环境没有重现问题。而为何后来测试环境的定时 JOB 也全部罢工了,原来是在我自测时,数据量还不是很大,经询问,后来同事全量执行了一遍迁移脚本,数据量变大了..

幸好处于双写阶段,晚上用户量又不是很大,才没有酿成大祸-_-。

定时任务罢工详解:SpringBoot 中 @Scheduled 执行原理

反思:

1、想办法模拟大数据量的自测场景

2、上线前“杜绝”慢查询语句

3、针对大数据量的查询 JOB,优化成分段 JOB

参考

  • https://stackoverflow.com/questions/44534258/spring-scheduler-stops-working-for-my-cron-expression
  • https://blog.csdn.net/weixin_34261415/article/details/88811563
  • https://blog.csdn.net/qq_32157851/article/details/84870403
  • https://blog.csdn.net/zhaominpro/article/details/84561966
  • https://juejin.im/post/5b76beefe51d45389d3b2b81
0 条回应