xxl-job

105 阅读4分钟

简介

概述

XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。

特性

  • 弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会重新分配任务;
  • 注册中心:执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时,也支持手动录入执行器地址;
  • 任务状态:支持动态开启、关闭任务,支持及时终止运行中的任务;
  • 一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行
  • 触发策略:Cron触发、固定间隔触发、固定延时触发、API(事件)触发、人工触发、父子任务触发;
  • 路由策略:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等;
  • 实时日志:支持在线查看调度结果,并且支持以Rolling方式实时查看执行器输出的完整的执行日志;
  • 调度过期策略:调度中心错过调度时间的补偿处理策略,包括:忽略、立即补偿触发一次等;
  • 阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖之前调度;
  • 任务超时控制:支持自定义任务超时时间,任务运行超时将会主动中断任务;
  • 任务失败重试:支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;其中分片任务支持分片粒度的失败重试;
  • 任务进度监控:支持实时监控任务进度;
  • 运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
  • 线程池隔离:调度线程池进行隔离拆分,慢任务自动降级进入”Slow”线程池,避免耗尽调度线程,提高系统稳

xxl-job的使用

客户端配置

image-20250406124246839.png

使用tips

image-20250406123931403.png

  1. 任务处理器必须注入spring容器才能生效

  2. 同一个执行器下,不能存在同名的任务处理器

  3. 在服务端定义任务时,通过JobHandler输入框指定任务处理器

  4. 使用XxlJobHelper.log()打印的日志才能在查看日志时被读取。

  5. 使用XxlJobHelper.getJobParam()在任务处理器获取任务参数

  6. 使用XxlJobHelper.handleFail()、XxlJobHelper.handleSuccess()设置任务处理器的执行结果

  7. 使用下列方法获取分片参数

    int shardIndex = XxlJobHelper.getShardIndex();
    int shardTotal = XxlJobHelper.getShardTotal();
    

xxl-job客户端

客户端的启动流程

定义xxl-job客户端,其中一个步骤是将XxlJobSpringExecutor注入spring容器,可见XxlJobSpringExecutor就是xxl-job客户端的启动入口。

XxlJobSpringExecutor继承了XxlJobExecutor,实现了AppliactionAware、SmartInitializingSingleton、DisposableBean接口。它们的作用依次是:

  1. 父类XxlJobExecutor定义了启动客户端的主要步骤。
  2. 通过实现AppliactionAware接口,可以通过setApplicationContext方法得到spring中ApplicationContext对象。
  3. 通过实现SmartInitializingSingleton接口,当所有单例bean被实例化之后,XxlJobSpringExecutor实现的afterSingletonsInstantiated方法会被调用。
  4. 通过实现DisposableBean接口,当XxlJobSpringExecutor的bean被销户时,XxlJobSpringExecutor实现的destroy方法会被调用。

重点关注SmartInitializingSingleton的afterSingletonsInstantiated方法,XxlJobSpringExecutor对它的实现是:

    @Override
    public void afterSingletonsInstantiated() {

        // init JobHandler Repository
        /*initJobHandlerRepository(applicationContext);*/

        // init JobHandler Repository (for method)
        initJobHandlerMethodRepository(applicationContext);

        // refresh GlueFactory
        GlueFactory.refreshInstance(1);

        // super start
        try {
            super.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

可以看到最后调用XxlJobSpringExecutor的父类的start(),XxlJobExecutor的start()的逻辑是:

 // ---------------------- start + stop ----------------------
    public void start() throws Exception {

        // init logpath
        XxlJobFileAppender.initLogPath(logPath);

        // init invoker, admin-client
        initAdminBizList(adminAddresses, accessToken);


        // init JobLogFileCleanThread
        JobLogFileCleanThread.getInstance().start(logRetentionDays);

        // init TriggerCallbackThread
        TriggerCallbackThread.getInstance().start();

        // init executor-server
        initEmbedServer(address, ip, port, appname, accessToken);
    }

从注释中可以看出xxl-job的启动流程:

  1. init JobHandler Repository:初始化任务处理器。
  2. refresh GlueFactory:刷新GlueFactory工厂
  3. init logpath:初始化日志文件夹。
  4. init invoker, admin-client:初始化xxl-job服务端的client。
  5. init JobLogFileCleanThread:初始化日志文件清理线程
  6. init TriggerCallbackThread:创建触发器回调线程
  7. init executor-server:初始化任务执行器内置服务
  8. 在第七步,还初始化了任务执行器注册线程

任务执行器和任务处理器的关系

image-20250407104126972.png

@XxlJob和任务处理器的关系

image-20250407105734849.png

任务处理器和任务线程的关系

image-20250407110603987.png

xxl-jo的一次调度过程

image-20250407103601742.png

xxl-job的日志查看

xxl-job服务端

时间轮调度

快慢线程池