执行器流程
-
配置类中注入bean:XxlJobSpringExecutor
-
XxlJobSpringExecutor实现接口SmartInitializingSingleton。在所有单例bean实例化之后,再次遍历所有单例bean,执行实现这个接口的回调方法afterSingletonsInstantiated
-
afterSingletonsInstantiated方法执行
①获取类中标记@XxlJob注解的方法。放入map中,key:Method,Vaule:XxlJob注解类
②registJobHandler(XxlJobExecutor中方法。XxlJobExecutor是XxlJobSpringExecutor的父类)。
registJobHandler(xxlJob, bean, executeMethod);
将Method封装为MethodJobHandler(里面包含目标类,可以直接调用方法执行)。获取XxlJob注解中的value属性,获取到执行的方法名称name。
③将name作为key,MehtodJobHandler作为value注入到jobHandlerRepository属性中。
jobHandlerRepository是XxlJobExecutor的属性。类型为 ConcurrentMap<String, IJobHandler>。 -
GlueFactory.refreshInstance(1);根据输入的参数创建一个GlueFactory类。
-
调用父类XxlJobExecutor的start()方法。
①XxlJobFileAppender.initLogPath(logPath);
初始化logPath。初始化日志文件。如果没有指定,默认/data/applogs/xxl-job/jobhandler
②initAdminBizList(adminAddresses, accessToken);
根据adminAddresses,accessToken初始化AdminBize。构建AdminBizClient,这个类可以执行Admin服务中的回调,注册,取消注册方法。里面封装了远程调用的细节。将创建的AdminBizeClient存到到XxlJobExecutor的属性adminBizList中。
private static List adminBizList;
③ JobLogFileCleanThread.getInstance().start(logRetentionDays);
JobLogFileCleanThread是一个单例类。有core包提供。它的职责就是日志文件清理。开启一个线程,定时去清理日志文件。
④ TriggerCallbackThread.getInstance().start();
TriggerCallbackThread也是一个单例类。有core包提供。触发器回调,它会创建两个线程去执行轮询逻辑。
triggerCallbackThread(触发回调线程):
private LinkedBlockingQueue callBackQueue = new LinkedBlockingQueue();
从回调阻塞队列里面通过阻塞方式(take方法)取出队列中一个任务。如果不为空,取出队列中所有任务放入内部的一个集合中,并清空阻塞队列。
doCallback方法执行内部的集合中的所有任务。通过adminBiz代理,调用admin服务的回调方法。返回结果写入日志中。失败的写入到失败文件。
triggerRetryCallbackThread(触发重试回调线程):
重试回调线程就是从失败文件中取任务,再次执行。
⑤ initEmbedServer(address, ip, port, appname, accessToken);
初始化内置服务器。初始化一个EmbedServer对象,调用该对象的start方法:
初始化一个执行器的代理对象:
executorBiz = new ExecutorBizImpl();
定义一个线程,启动这个线程:
线程中通过netty初始话流程创建一个ServerSocketChannel。监听一个端口,开启服务。
请求处理类EmbedHttpServerHandler。
注册服务到admin。注册通过ExecutorRegistryThread单例类执行start方法。start方法开启一个线程,如果没有终止,一直执行。run方法中通过获取adminBiz代理对象,调用对象的registry方法,向Admin注册当前executor方法。休眠30秒,继续执行。如果执行器设置stop = true,则退出while循环,通过adminBiz代理对象,调用admin的取消执行器方法。目的:将当前服务信息注册到admin。如果ip未配置,默认取当前服务的ip。数据会被保存到admin服务端的表xxl_job_registry中
。 -
ExecutorBizImpl中对请求的处理
当admin与executor建立连接。通过解码获取请求的HttpMethod,rui,requestData,accessToken。通过线程池,执行请求。
Object responseObj = process(httpMethod, uri, requestData, accessTokenReq);
①基础校验,校验httpMethod,uri,accesstoken。
②根据uri,executorBiz代理类执行队形的方法。常用的有心跳方法,运行方法,杀死服务方法等。
jobThread中的run方法执行:
通过excutor中xxljob上标注的name,在xxljobexecutor类中的jobHandlerRepository属性中,通过key获取到对应的value(MehtodJobHandler)。
注册一个job线程,放入任务的jobid(uuid唯一),jobHandler。启动job线程,异步执行请求。主流程中将请求放入到jobThread的blockQueue
中。然后jobThread的run方法就从阻塞队列中取任务执行以下流程:
①执行handler的init方法。
②job线程中有一个triggerQueue队列。从队列中poll一个triggerParam,如果不为空,triggerLogIdSet集合中移除当前的traiggerParam的logId对应的记录。
③执行handler的executor方法。
④TriggerCallbackThread将封装好的方法执行结果放入到阻塞队列。有回调线程调用admin的回调方法执行。
特殊情况。执行30次后,阻塞队列中没有任务。将jobThread从xxlJobExecutor中移除,并调用jobThread的toStop方法,调用当前线程中断。
xxljobexecutor中就保存了以下内容:
(1)jobHandlerRepository:保存xxljob注解中name和对应的MethodHandler
(2)adminBizList:保存Admin服务的adminbiz代理对象
(3)jobThreadRepository:保存处理admin请求的jobThread对象
Admin初始化流程
- 配置类初始化的时候执行XxlJobScheduler类的init方法。
- XxlJobScheduler的init方法
①initI18n
国际化。暂不研究
②JobTriggerPoolHelper.toStart();
初始化触发器线程池。JobTriggerPoolHelper类中初始化两个线程池:一个快线程池,一个慢处理线程池。当任务的超时时间设置超过10秒时,我们认为其为慢任务,使用慢触发器线程池去处理,没有设置超时间和超时时间小于10s的我们认为其运行很快交由快触发器线程池处理。
③JobRegistryHelper.getInstance().start();
初始化注册,移除线程池
。初始化监听器线程
,并启用这个监听器线程。
监听器线程,while循环一直执行,更新执行器信息。
④JobScheduleHelper.getInstance().start();
定时任务的执行线程。从定时任务中取出任务,通过JobTriggerPoolHelper.trigger触发任务。JobTriggerPoolHelper就是上面写的里面会初始化两个线程池。定时任务里面是调用XxlJobTrigger.trigger触发任务。找到对应的执行器,processTrigger方法处理任务。通过执行器的地址信息获取执行器的代理对象executorBiz,执行run方法。
补充:2023-06-03.服务端执行器:自动注册方式的机器地址列表获取。
客户端会定时(默认间隔30秒)将服务信息(包含服务ip和端口,执行器名称)注册到服务端的表xxl_job_registry中。
服务端也有要给定时任务:JobRegistryHelper
。执行器表xxl_job_group
中查询类型为自动注册类型的执行器。然后根据执行器名称去JobRegistryHelper
表中查找默认90s还存活的机器地址。更新到表xxl_job_group
中对应的执行器上。