从XxlJobSpringExecutor开始
两个步骤:
1、initJobHandlerMethodRepository(applicationContext); //注册定义的JobHandler 2、super.start(); //启动
1. initJobHandlerMethodRepository:
将应用中自定义的JobHandler 扫描出来 @XxlJob,并注册到 ConcurrentMap<String, IJobHandler> jobHandlerRepository中。
源码如下:
// generate and regist method job handler
for (Map.Entry<Method, XxlJob> methodXxlJobEntry : annotatedMethods.entrySet()) {
Method executeMethod = methodXxlJobEntry.getKey();
XxlJob xxlJob = methodXxlJobEntry.getValue();
// regist
registJobHandler(xxlJob, bean, executeMethod);
}
进入registJobHandler(xxlJob, bean, executeMethod)方法
// registry jobhandler
registJobHandler(name, new MethodJobHandler(bean, executeMethod, initMethod, destroyMethod));
// ---------------------- job handler repository ----------------------
private static ConcurrentMap<String, IJobHandler> jobHandlerRepository = new ConcurrentHashMap<String, IJobHandler>();
jobHandlerRepository.put(name, jobHandler);
2. start():
先看源码
public void start() throws Exception {
// init logpath
XxlJobFileAppender.initLogPath(logPath);
// init invoker, admin-client
initAdminBizList(adminAddresses, accessToken, timeout);
// init JobLogFileCleanThread
JobLogFileCleanThread.getInstance().start(logRetentionDays);
// init TriggerCallbackThread
TriggerCallbackThread.getInstance().start();
// init executor-server
initEmbedServer(address, ip, port, appname, accessToken);
}
TriggerCallbackThread.getInstance().start():
会创建两个线程triggerCallbackThread、triggerRetryCallbackThread 并启动。
initEmbedServer(address, ip, port, appname, accessToken):
创建一个http server,用于接收服务端的操作指令,如 "/beat" "/idleBeat" "/run" "/kill" 等。实际上会调用ExecutorBizImpl对象的方法
同时会将自己注册到服务端中 startRegistry(appname, address);
ExecutorRegistryThread.getInstance().start(appname, address);
继续点进去
我们还能看到每次注册后,会睡眠默认30s
TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
ExecutorBizImpl 这个对象就是执行具体的操作指令
执行job的代码截图:ExecutorBizImpl.run()方法
先loadJobThread(第一次为null)—— 从jobThread中取出jobHandle —— 如果取不到jobHandle, 则从map中取出jobHandle(因为jobHandle都注册到ConcurrentMap<String, IJobHandler> jobHandlerRepository中了)
拿到jobHandler之后,会创建JobThread对象 jobThread = XxlJobExecutor.registJobThread(triggerParam.getJobId(), jobHandler, removeOldReason);
然后 jobThread.pushTriggerQueue(triggerParam) 将请求参数放入triggerQueue中,jobThread再去执行jobHandle
创建XxlJobContext对象后,调用 handler.execute();执行job方法。
执行完成后会处理返回值,比如异常时的信息。
执行完成后会回调XXL Job服务器:adminBiz.callback(callbackParamList)
至此,一个执行过程就完成了。
总结一下:
- 客户端项目启动后,会扫描自定义的jobHandle(即自己写的定时任务的方法),并注册到jobHandlerRepository的Map中。
- 会初始化一些线程:triggerCallbackThread(用于回调XxlJob服务器)、triggerRetryCallbackThread(应该是重试逻辑吧??);
- 初始化一个http server,用于接收XxlJob服务器的http请求命令,如/run。
- 将客户端自己注册到XxlJob服务器,每30s注册一次。
- 当XxlJob发起/run时,客户端先从内存中获取jobHandle,(第一次会创建JobThread),再 triggerQueue.add(triggerParam);
- JobThread去消费triggerQueue,执行 handler.execute(),再处理执行结果是成功还是失败。再将结果通过回调接口返回给XXL Job服务器。