0.引言
我们都会用xxl-job,但很少有人能够说清楚xxl-job的任务触发机制,面临任务阻塞、服务重启如何处理任务,本期我们就来一起看看xxl-job的任务触发机制
1. 调度过期策略
我们在配置策略时可以看到有一个调度过期策略
配置,也许你知道这是任务超期时的处理规则,但你有没有想过什么时候任务会过期?
定时任务执行时,如果服务重启、服务器资源不足,上次调度阻塞这些原因都会导致当前任务错过触发时间。
而xxl-job对此的处理方式是两种:
- 忽略:如果过期超过了5s,则忽略本次,从当前时间开始计算下次触发时间
这种配置适用于,下次执行可以补救上次任务未执行,比如定时更新数据库,如果上次没更新,那么下次一起更新即可
- 立即触发一次:如果超期没有超过5s,则立即执行一次任务,并从当前时间开始计算下次触发时间
这种配置适用于尽可能期望每次任务都能触发的任务,但需要考虑到,如果超期过了5s,任务仍然不会执行
2. 任务调度步骤
xxl-job的任务调度整体分为3步执行:
1、服务端(调度器) 向 客户端(执行器)发送http调度请求
2、执行器执行定时任务
3、执行器http回传调度器执行结果,调度器接收执行结果的服务实际上是一组api接口,即开放了一组回调接口
3. 任务触发机制
xxl-job的任务触发早期是通过Quartz来进行的,目前已经更新为时间轮管理
1、首先会有一个任务表来记录所有要执行的任务及时间点
2、单独启动一个scheduleThread
线程来从任务表获取近5s要执行的任务,获取时如果该任务的触发时间点已经达到,则立即执行,否则就将任务时间点除以1000,再60求余,放到时间轮中
3、这个所谓的时间轮,其实就是一个Map,key是0~60,value是任务ID集合,即Map<Integer, List<Integer>> ringData
,为保证线程安全,使用了ConcurrentHashMap
4、另外还有一个线程ringThread
会不断用当前时间60求余,然后从时间轮中取出对应key的任务列表,进行执行。如此实现了定时任务的触发。
上述逻辑,在源码JobScheduleHelper
类中可以看到
5、综上,xxl-job的定时任务的触发,核心在于时间轮上的处理