本文结合源码讲解了一次任务执行的全生命周期:执行、结果回调、失败重试和告警。结合任务在执行器中的处理流程,我们就看透了任务执行的全貌。
参照上一篇博文 xxl-job执行器的任务执行流程
一 启动调度平台
调度平台是一个springboot的web工程,使用Tomcat作为web服务器。
XxlJobAdminConfig配置类,实现了InitializingBean,Spring容器在完成Bean的属性设置后,会自动调用afterPropertiesSet(),其中创建了XxlJobScheduler实例。
XxlJobScheduler在init()方法中,完成了上下文环境准备,涉及7个方面:
// 国际化
initI18n();
// 启动TriggerPool线程池
JobTriggerPoolHelper.toStart();
// 启动处理注册的线程池
JobRegistryHelper.getInstance().start();
// 启动失败重试、告警线程
JobFailMonitorHelper.getInstance().start();
// 启动任务结果丢失处理线程
JobCompleteHelper.getInstance().start();
// 启动处理结果回调的线程
JobLogReportHelper.getInstance().start();
// 启动任务调度线程
JobScheduleHelper.getInstance().start();
二 任务的一次执行
2.1 JobTriggerPoolHelper类
创建了两个线程池,来异步执行Trigger请求。基于一分钟内某个job的Trigger耗时统计,决定本次使用哪个线程池。
2.1.1 fast/slow线程池
可见,它俩的
corePoolSize都是10,而fastTriggerPool有更大的maximumPoolSize、尺寸更小的任务队列。
当Trigger请求并发很高时,fastTriggerPool更有机会创建救急线程,更及时地执行Trigger。
2.1.2 Trigger的快慢判定
当一个Trigger执行耗时超过500ms,即认为超时了。对jobTimeoutCountMap中计数加1。
对jobTimeoutCountMap,每分钟清空一次。即计数周期是每一分钟。
处理Trigger时,默认使用fastTriggerPool。但某个任务在1分钟内超时10次以上时,改用slowTriggerPool。
2.2 XxlJobTrigger类
任务的一次执行,最终会调用XxlJobTrigger.trigger,其中逻辑如下:
- 入参failRetryCount如果小于0,则取xxl_job_info表的executor_fail_retry_count字段,即页面配置时设置的值。
- 路由策略为
SHARDING_BROADCAST即分片广播时,则触发与执行器数量相同次数的调度,在每个实例都执行任务; - 其他路由策略,只触发一次调度。
- 调用
XxlJobTrigger.processTrigger方法,完成:- 保存执行日志记录,
- 创建
TriggerParam实例 - 根据路由策略选取一个目标执行器
- 发送调度请求
- 记录调度日志,如下图
2.3 ExecutorBizClient类
根据执行器address,获取对应的ExecutorBizClient。
ExecutorBizClient是与某个执行器实例通信的客户端,用于发送http请求,支持5个指令:beat、idleBeat、run、kill、log。
三 结果回调
在执行器完成任务执行后,会通过callback接口给调度平台同步结果。由JobCompleteHelper类处理回调:
callbackThreadPool异步处理回调请求:
- 查询XxlJobLog记录,更新部分字段的值;
- 在执行结果为成功时,在XxlJobCompleter中触发子任务。
monitorThread的作用:每分钟检查一次,将调度记录停留在 "运行中" 状态超过10min,且对应执行器心跳注册失败不在线,则将本地调度主动标记失败。
四 失败重试和告警
4.1 重试
在JobFailMonitorHelper类中,启动了monitorThread线程:
- 每10秒查询xxl_job_log表中调度失败或执行失败,且尚未告警过的任务;
- 如果executorFailRetryCount>0,则触发一次执行,executorFailRetryCount减1;
- 调用
JobAlarmer.alarm,根据配置的方式(如邮件、短信等)发送告警。
4.2 告警
告警方式支持扩展,实现JobAlarm接口,交由spring创建bean即可。
默认提供了邮件告警实现
EmailJobAlarm,可在任务管理页配置收邮箱。
而发件箱在application.properties中提供,注意
spring.mail.password是指授权码,不是登录密码。
告警邮件示例
五 总结
- 根据Trigger的耗时,提供了快、慢两个线程池;
- 路由策略为分片广播时,会调度每一台执行器实例,用broadcastIndex、broadcastTotal传递分片信息;
- 通过异步回调,执行器告诉调度平台任务执行结果;
- 对于失败的调度或执行,如果任务配置了重试次数和告警邮箱,会异步进行重试或告警。