xxl-job任务执行器调度的实现机制
整体上来讲,就是在xxl-job-admin中通过调用任务执行器的HTTP接口,实现对任务执行器的调度。
具体又可以分为2个层面进行剖析,如下:
任务执行器侧:
当在项目中引入xxl-job-core
组件之后,如果是在Spring容器环境中,会通过XxlJobSpringExecutor
组件的afterSingletonsInstantiated()
方法做如下2件事情:
第一步,解析使用了@XxlJob
注解的任务执行器方法,并保存到一个HashMap
结构中,Key为@XxlJob
注解的value()
,值为MethodJobHandler
对象。
第二步,启动一个内置的http服务器(基于Netty框架实现),这样就可以确保xxl-job-admin
能够通过HTTP方法调用的方式访问到任务执行器,并通过解析HTTP参数的方式找到在第一步中解析并保存起来的任务执行器方法并执行。
任务调度中心侧:
通过XxlJobScheduler
实现对任务执行器数据的读取并调用,本质上是调用任务执行器暴露的HTTP方法,当同时存在多个任务执行器时,需要实现对任务执行器的调度选择,通过ExecutorRouter
来实现。
xxl-job高可用实现原理
xxl-job-admin的高可用通过部署多实例来实现,当部署多实例之后如何确保同时只有一个admin实例会发起调度呢?使用了MySQL数据库的悲观锁机制,详见:JobScheduleHelper.start()
方法。
任务执行器的高可用也是通过部署多实例来实现,当任务执行器也部署多实例之后如何确保同时只会调度到一个执行器上呢?在xxl-job-admin
是通过不同ExecutorRouter
组件实现来控制的,以ExecutorRouteFirst
为例,总是返回执行器列表中的第一个:
public class ExecutorRouteFirst extends ExecutorRouter {
@Override
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList){
return new ReturnT<String>(addressList.get(0)); // 总是返回执行器列表中的第一个
}
}
关于在xxl-job-admin中对任务执行器的调度控制,详见:XxlJobTrigger.processTrigger()
方法。
【参考】
XXL-JOB调度中心HA及高可用方案
XXL-Job高可用集群搭建
xxl-job高可用部署
xxl-job 实现高可用
3千字带你搞懂XXL-JOB任务调度平台
MySQL的SELECT ...for update