一、概述
执行器SDK是整个分布式任务调度平台中,接收调度中心派发的任务请求,并执行任务的模块,使用方需要接入执行器SDK,实现任务执行的逻辑。它主要包含以下功能:
- 接收调度中心派发的任务请求。
- 任务缓存到内存队列,并在指定时间执行任务。
- OpenApi接口交互签名与验签。
- 上报任务的执行结果。
- 执行器心跳上报,每3秒一次心跳,表明执行器在线。
- 执行器与任务的自动注册,每30s自动注册一次。
二、整体架构
1. 模块架构

三、核心模块设计
1. 提前调度
任务会提前3秒(可配置)被调度器派发到执行器,执行器接收到任务后,会将任务添加到延迟队列中,延迟队列会在任务的执行时间到达后,将任务派发到执行线程池中执行。 这样设计的目的是为了提高任务执行的及时性,能够有效的规避因为网络延迟、调度延迟等各种原因导致任务执行时间滞后。
2. 自动注册
执行器启动时,会自动注册执行器和任务信息到调度器中,只需要在管理后台启动任务即可使用,不需要手动在管理后台配置信息。启动时会先注册执行器再注册任务信息,之后每30秒会自动注册一次,以确保信息的及时同步到调度器,其中已经存在的任务信息不会被覆盖, 也就是说,管理后台中修改过的信息,自动注册机制不会去影响,它只在第一次有效。 执行器的自动注册依赖于三个方面的元数据信息:
- 执行器的配置信息:
- 对于原生Java版本:需要手动通过代码配置。
- 对于SpringBoot版本:可以通过Spring的配置文件配置,也可以通过Bean来实例化对象
cn.horace.cronjob.executor.starter.config.ExecutorStarterConfig
。
- 预定义的任务对象:
- 对于原生Java版本:需要手动实例化对象,并设置到执行器的配置中。
- 对于SpringBoot版本:只需要将任务类交给Spring容器管理即可,不需要手动实例化对象。
- 注解标识的任务信息:任务的配置信息由
cn.horace.cronjob.executor.annotation.TaskConfig
注解来配置决定,它需要放在任务类上,使用时按需修改其中各项配置即可。
3. 线程池
执行器中,总共有三个关键的线程池,分别是:
- 调度线程池,核心线程数为3个,用在3秒一次的心跳和30秒一次的自动注册。
- 执行线程池,用于执行实际的任务,核心线程数为5个,最大80个,空闲5分钟后销毁。
- 结果上报线程池,用于上报任务结果,核心线程数为5个,最大80个,空闲5分钟后销毁。
执行线程池和结果上报线程池分开的目的是为了避免相互影响,而且控制了核心线程数,开销并不大。另一个值得一提的是任务的派发,这里是固定一个线程永不停歇的从延迟队列获取任务,如果没有任务,那么线程会阻塞,直到有任务到达或者超时,直到下一轮, 这里不需要线程池的原因是一个线程就能满足,拿到任务后就会派发给执行线程执行,所以它的开销很小。
4. 优雅下线
优雅下线的设计目的是为了执行器关闭时可以做好收尾工作,规避因关闭、重启导致数据丢失和不一致性的问题。简单来说,在执行器关闭时,会有以下的行为:
- 向调度器发送下线请求。
- 停止接收任务的派发
- 停止心跳。
- 停止自动注册。
- 等待现有任务执行完毕。
- 等待结果上报线程池中的任务执行完毕。
为了达到上述的效果,避免收到关闭命令时,网络通道等相关资源已关闭,执行器SDK修改了ShutdownHook
的默认行为,优雅下线的动作会先于系统默认的hook执行,因此确保关闭前所依赖的资源可用。细节可查看源码cn.horace.cronjob.commons.utils.shutdown.ShutdownHookManager
。
5. 定期心跳
定期心跳的目的是为了能够上报执行器的状态,以便于调度器能够及时的感知到执行器的存在,从而能够及时的进行任务的调度。如果执行器超过30秒没有心跳,则会置为下线状态,不会再派发任务。另外结合优雅关闭,执行器关闭时,会主动下线自己,以便调度器及时感知。
6. 安全性设计
执行器与调度器之间的交互接口,均采用签名校验的方式,以保证数据的安全性。签名秘钥由调度器的配置决定,执行器需要保持一致。接入方在接入时,可以按需自定义,以免和大众一样,签名验证算法简要概括如下:
- 发送端将待签名参数按照参数名称的字典序排序。
- 将排序后的参数按照key=value的格式拼接成一个字符串。
- 将拼接后的字符串和秘钥进行MD5加密。
- 将加密后的MD5值作为签名参数,添加到请求参数中。
- 接收端将请求参数中的签名参数取出,按照相同的算法进行签名。
- 将签名后的MD5值与请求参数中的签名参数进行比较,如果一致,则认为请求是合法的。
详情可查阅签名工具类cn.horace.cronjob.commons.utils.SignUtils
。