一、概述

执行器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

最后更新