xxl-job调度平台之任务执行

700 阅读3分钟

本文结合源码讲解了一次任务执行的全生命周期:执行、结果回调、失败重试和告警。结合任务在执行器中的处理流程,我们就看透了任务执行的全貌。

参照上一篇博文 xxl-job执行器的任务执行流程

一 启动调度平台

调度平台是一个springboot的web工程,使用Tomcat作为web服务器。 image.png

XxlJobAdminConfig配置类,实现了InitializingBean,Spring容器在完成Bean的属性设置后,会自动调用afterPropertiesSet(),其中创建了XxlJobScheduler实例。 image.png XxlJobSchedulerinit()方法中,完成了上下文环境准备,涉及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线程池

image.png 可见,它俩的corePoolSize都是10,而fastTriggerPool有更大的maximumPoolSize、尺寸更小的任务队列。 image.png image.png 当Trigger请求并发很高时,fastTriggerPool更有机会创建救急线程,更及时地执行Trigger。

2.1.2 Trigger的快慢判定

当一个Trigger执行耗时超过500ms,即认为超时了。对jobTimeoutCountMap中计数加1。 image.png image.png 对jobTimeoutCountMap,每分钟清空一次。即计数周期是每一分钟。 image.png 处理Trigger时,默认使用fastTriggerPool。但某个任务在1分钟内超时10次以上时,改用slowTriggerPool。 image.png

2.2 XxlJobTrigger类

任务的一次执行,最终会调用XxlJobTrigger.trigger,其中逻辑如下:

  • 入参failRetryCount如果小于0,则取xxl_job_info表的executor_fail_retry_count字段,即页面配置时设置的值。 image.png
  • 路由策略为SHARDING_BROADCAST即分片广播时,则触发与执行器数量相同次数的调度,在每个实例都执行任务;
  • 其他路由策略,只触发一次调度。 image.png
  • 调用XxlJobTrigger.processTrigger方法,完成:
    • 保存执行日志记录,
    • 创建TriggerParam实例
    • 根据路由策略选取一个目标执行器
    • 发送调度请求
    • 记录调度日志,如下图 image.png

2.3 ExecutorBizClient类

根据执行器address,获取对应的ExecutorBizClientimage.png ExecutorBizClient是与某个执行器实例通信的客户端,用于发送http请求,支持5个指令:beat、idleBeat、run、kill、log。 image.png image.png

三 结果回调

在执行器完成任务执行后,会通过callback接口给调度平台同步结果。由JobCompleteHelper类处理回调: image.png

callbackThreadPool异步处理回调请求:

  • 查询XxlJobLog记录,更新部分字段的值; image.png
  • 在执行结果为成功时,在XxlJobCompleter中触发子任务。 image.png

monitorThread的作用:每分钟检查一次,将调度记录停留在 "运行中" 状态超过10min,且对应执行器心跳注册失败不在线,则将本地调度主动标记失败。

四 失败重试和告警

4.1 重试

JobFailMonitorHelper类中,启动了monitorThread线程:

  • 每10秒查询xxl_job_log表中调度失败或执行失败,且尚未告警过的任务;
  • 如果executorFailRetryCount>0,则触发一次执行,executorFailRetryCount减1; image.png
  • 调用JobAlarmer.alarm,根据配置的方式(如邮件、短信等)发送告警。

4.2 告警

告警方式支持扩展,实现JobAlarm接口,交由spring创建bean即可。 image.png 默认提供了邮件告警实现EmailJobAlarm,可在任务管理页配置收邮箱。 image.png 而发件箱在application.properties中提供,注意spring.mail.password是指授权码,不是登录密码。 image.png image.png

告警邮件示例 image.png

五 总结

  • 根据Trigger的耗时,提供了快、慢两个线程池;
  • 路由策略为分片广播时,会调度每一台执行器实例,用broadcastIndex、broadcastTotal传递分片信息;
  • 通过异步回调,执行器告诉调度平台任务执行结果;
  • 对于失败的调度或执行,如果任务配置了重试次数和告警邮箱,会异步进行重试或告警。