xxl-job 源码这么容易懂,那就随手画图分析下 xxl-job 执行器的原理

3,786 阅读3分钟

声明

阅读本文前, 需要对 xxl-job 的使用有所了解。

正文

本文内容基于 xxl-job v2.2.0 源码。

一、调度中心和执行器

下面是 xxl-job v2.x 的架构图, 该图中包含了两大核心模块, 分别是 调度中心执行器.

  • 调度中心

    简单来讲就是一个 管理系统, 用户通过系统提供的管理界面可以创建任务、编辑任务、手动触发任务以及查看任务执行日志, 另外系统后台会不停地把需要执行的任务从数据中心的 任务表 中扫描出来, 然后一个个去触发任务.

  • 执行器

    当任务被触发时, 不管是定时触发还是手动触发, 调度中心都会向执行器发送 http 请求, 由执行器负责任务的执行.

在这里插入图片描述

xxl-job 源码目录

在这里插入图片描述

二、创建任务

在这里插入图片描述

从图中可以看出:

  • 任务执行参数包含了诸多内容, 比如任务阻塞处理策略,执行策略等等。
  • 运行模式选择 Bean,这也是本文讲解的重点。
  • 任务执行前,还需要指定一个具体的 JobHandler 去执行。
  • 如果是周期性的任务,它在执行的过程中,我们是可以随时调整执行参数的。比如 JobHandler(这点很重要!!!)。

三、定义任务

@Component
public class SampleXxlJob {
    /**
     * 1、简单任务示例(Bean模式)
     */
    @XxlJob("demoJobHandler")
    public ReturnT<String> demoJobHandler(String param) throws Exception {
        // doSomething
        return ReturnT.SUCCESS;
    }
}

上面通过 Spring 框架注解和 Xxl-Job 框架注解定义了一个任务, 当执行器启动时, 会扫描到这个 SampleXxlJob中的 demoJobHandler方法, 并将该方法封装成一个JobHandler具体实现为MethodJobHandler ) 对象(该 Handler 中的 execute 方法为任务的具体执行逻辑),并把该 JobHandler 注册到容器1中。容器1 的定义如下:

// key 为 XxlJob 注解中的 bean 名称
// value 为 JobHandler
ConcurrentMap<String, IJobHandler> jobHandlerRepository = new ConcurrentMap();

四、任务执行流程

当一个任务被触发(不管是手动触发还是自动触发)时:

  1. 调度中心 会将任务执行参数封装到 TriggerParam 通过 POST 请求传给 执行器.
  2. 如果该任务是第一次执行, 会 new 一个新线程并启动。 JobThread 线程启动后,它会被注册到容器2 中。容器2 定义如下,最后会把 TriggerParam 推送到 线程中维护的一个队列。
这个新线程的名字为 JobThread, 该线程和 JobHandler 是一一绑定的。我们可以通过 JobThread 获取到此 JobHandler。

// key 为任务 id, jobId
// value 为 JobThread 对象
private static ConcurrentMap<Integer, JobThread> jobThreadRepository = new ConcurrentHashMap<Integer, JobThread>();
  1. JobThread 线程启动后,run 方法会不断从 队列 中读取任务执行参数。
  2. 读取到执行参数后, 会把执行参数交给 JobHandler#execute 方法去执行任务。

JobThread 中维护了一个队列, 任务每执行一次,就把执行参数推到该队列中,JobThread 启动后就一直从队列中读取执行参数,直到任务停止。

如果该任务第二次执行,会通过 jobId 从容器 jobThreadRepository 中获取之前缓存的 JobThread

  • 如果 JobThread 不为空,则取出 JobThread 中的 JobHandler。

  • 根据前面提到的,因为任务每次执行时, JobHandler 是可以更换的。所以这里会判断此次任务执行的 JobHandler 是不是跟上一次的一样。如果不一样就要用新的替换掉旧的。并把缓存的 JobThread 注销掉。重新 new 一个新的 JobThread。

  • 如果 JobHandler 没有发生改变,就复用。

五、源码入口

com.xxl.job.core.biz.impl.ExecutorBizImpl#run

com.xxl.job.core.thread.JobThread#run

参考文档

xxl-job 官方文档