实际生产中,我们更多的是运行模式是xxl-job到点自动触发任务并执行。本篇博客就来探讨xxl-job是如何自动执行定时任务的。
开篇
public class XxlJobAdminConfig implements InitializingBean, DisposableBean { ... }
【调度起始源头,相当于软件工程项目发包方】
XxlJobAdminConfig交由spring管理,因此会在调度端启动之时就会启动。
public class XxlJobScheduler { ... }
定时任务调度器。
XxlJobAdminConfig启动时就会初始化一个XxlJobScheduler对象并初始化;
XxlJobScheduler重要的初始化方法:
借助JobScheduleHelper工具类,核心代码在里面;
for (XxlJobInfo jobInfo: scheduleList) {
// 1、trigger
JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.CRON, -1, null, null, null);
}
JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.CRON, -1, null, null, null);
这个代码看起来很熟悉了。
请参阅博客
《折腾xxl-job系列之job手动执行调度过程》
利用了JobTriggerPoolHelper类的trigger方法来帮助我们执行job。
利用XxlJobTrigger.trigger(jobId, triggerType, failRetryCount, executorShardingParam, executorParam, addressList);
调用类【XxlJobTrigger】方法【trigger】。具体如下:
- 根据jobId获取XxlJobInfo完整对象。
- 记录xxl-job trigger start日志
- 初始化TriggerParam对象【该对象将要传给执行器】
- 初始化远程地址【主要是执行器的地址】
- 触发执行器,执行远端job逻辑。
- 记录日志【执行日志,执行后日志等】
看下我们的核心逻辑【触发执行器,执行远端job逻辑。】
类【XxlJobTrigger】
方法【public static ReturnT<String> runExecutor(TriggerParam triggerParam, String address)】
public interface ExecutorBiz ;// 执行器
获得ExecutorBiz 的实现类【在调度器端的实现为ExecutorBizClient】。
这个 runExecutor方法的主要逻辑:
利用执行器ExecutorBiz 去调度任务。
ExecutorBizClient的调度任务实现很简单,就是发送http请求至执行器端。把请求委托给执行器具体去处理。至此调度端主体结束;(发包方将软件工程发包出去)
【执行器端】【相当于承包工程的软件公司】
执行器以springboot执行器为例,springboot项目启动后,
XxlJobExecutor会初始化很多的内置类。
比较重要的当属
// job handler repository
private static ConcurrentMap<String, IJobHandler> jobHandlerRepository = new ConcurrentHashMap<String, IJobHandler>();
Key的值是@XxlJob("demoJobHandler")里面的value值, IJobHandler则是对应的方法的封装。这个变量保存了所有我们需要实现的具体的方法。IJobHandler则是我们的需要实现的一个一个具体的业务方法。
另:执行器端会开启一个netty服务;
public class EmbedServer { ... }
会启动一个端口为 9999的服务,【端口可以配置】。
该服务接收来自ExecutorBizClient的客户端请求。
在netty服务内部有这么一个执行器。【netty服务相当于软件公司的研发部门】
public class ExecutorBizImpl implements ExecutorBiz {...}
具体执行调度任务的执行器。
Netty服务内部也是线程池处理也是异步请求。最终由executorBiz执行调度任务;
executorBiz具体执行的方法如下(ExecutorBizImpl相当于项目经理,只管给下属分配任务,自己却不亲自下手):
- 从客户端获取job对应的参数
- 根据参数获取jobHandler,并获得jobThread.
jobThread = XxlJobExecutor.registJobThread(triggerParam.getJobId(), jobHandler, removeOldReason);
3.将任务数据放入到一个队列中供执行线程异步调用
// push data to queue
ReturnT<String> pushResult = jobThread.pushTriggerQueue(triggerParam);
任务执行类【相当于最终干苦力的程序员】
public class JobThread extends Thread{ ... }
核心处理逻辑:
- 从队列中获取将要执行的【IJobHandler】
- 调用jobhandler里面的具体实现逻辑。
- 回调线程调用回调方法,将具体的任务执行结果报告给调度平台。
以上是一个任务从开始到结束的整个过程,欢迎各位看官批评指正。