xxl-job源码解析(技术分享)

文章目录

1. 概念

1. 定时任务的基本概念

程序为解决一个信息处理任务而预先编制的工作执行方案,这就是定时任务,核心组成如下:

  • 执行器:负责管理应用运行时环境,用于调度定时任务。
  • 任务:任务执行的流程,是一个类,具体的业务。
  • 触发器:按照某种时间规则,执行具体的调度任务。

2. 定时任务的使用场景

日常开发中,定时任务主要分为如下两种使用场景:

时间驱动:

  • 对账单、日结
  • 营销类短信
  • MQ定时检查生产失败的消息

数据驱动:

  • 异步数据交换
  • 数据同步

3. 原生定时任务缺陷有哪些缺陷?

分布式技术应用的时代,原生定时任务的缺陷显得更为突出。结合传统项目与分布式微服务的架构,思考总结如下,欢迎各位大神给与补充:

  • 不支持集群多节点部署,需要自己实现避免任务重复执行的问题。
  • 不支持分片任务,处理有序数据时,多机器分片执行任务处理不同数据。
  • 不支持动态调整,不重启服务的情况下修改任务的参数。
  • 没有报警机制,当任务失败后没有报警机制通知。
  • 不支持生命周期统一管理,如不重启服务情况下关闭、启动任务。
  • 不支持失败重试,出现异常后任务终结,不能根据状态控制任务重新执行。
  • 无法统计任务数据,当任务数据量大的时候,对于任务执行情况无法高效的统计执行情况。

4. 基于当前 XXL-JOB 我们能做什么?

  • 执行器 HA(分布式):天生支持任务分布式执行,无需自己实现。任务"执行器"支持集群部署,可保证任务执行 HA;
  • 调度中心 HA(中心式):调度中心相当于传统调度任务的触发器,调度采用中心式设计,“调度中心”自研调度组件并支持集群部署,可保证调度中心 HA;
    在这里插入图片描述

2. 系统架构和整理流程

https://www.xuxueli.com/xxl-job/

2.1. 设计思想

  • 将调度行为抽象形成“调度中心”公共平台,而平台自身并不承担业务逻辑,“调度中心”负责发起调度请求。
  • 将任务抽象成分散的JobHandler,交由“执行器”统一管理,“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑。
  • 因此,“调度”和“任务”两部分可以相互解耦,提高系统整体稳定性和扩展性;

2.2. 架构图

在这里插入图片描述

2.3. 执行流程

在这里插入图片描述

3. 启动流程

3.1. 服务器启动

在这里插入图片描述
首先找到配置类 XxlJobAdminConfig, 可以发现该类实现 InitializingBean接口,这里直接看 afterPropertiesSet方法即可。

@Component
public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
    // ---------------------- XxlJobScheduler ----------------------

    private XxlJobScheduler xxlJobScheduler;

    @Override
    public void afterPropertiesSet() throws Exception {
        adminConfig = this;
		 // 初始化xxljob调度器	
        xxlJobScheduler = new XxlJobScheduler();
        xxlJobScheduler.init();
    }
    ...
}


public void init() throws Exception {
        // init i18n
        initI18n();

        // admin trigger pool start
        // 初始化触发器线程池
        JobTriggerPoolHelper.toStart();

        // admin registry monitor run
        /**
         * 30秒执行一次,维护注册表信息, 判断在线超时时间90s
         * 1. 删除90s未有心跳的执行器节点;jobRegistry
         * 2. 获取所有的注册节点,更新到jobGroup(执行器)
         */
        JobRegistryHelper.getInstance().start();

        // admin fail-monitor run 运行事变监视器,主要失败发送邮箱,重试触发器
        JobFailMonitorHelper.getInstance().start();

        // admin lose-monitor run ( depend on JobTriggerPoolHelper )
        // 将丢失主机调度日志置为失败
        JobCompleteHelper.getInstance().start();

        // admin log report start  统计一些失败成功报表
        JobLogReportHelper.getInstance().start();

        // start-schedule  ( depend on JobTriggerPoolHelper )
        /**
         * 调度器执行任务(两个线程 + 线程池执行调度逻辑)
         * 1. 调度线程50s执行一次;查询5s秒内执行的任务,并按照不同逻辑执行
         * 2. 时间轮线程每1秒执行一次;时间轮算法,并向前跨一个时刻;
         */
        JobScheduleHelper.getInstance().start();

        logger.info(">>>>>>>>> init xxl-job admin success.");
    }

3.2. 客户端启动

在这里插入图片描述
这里我们看XxlJobSpringExecutor,实现了 SmartInitializingSingleton 接口,实现该接口的当spring容器初始完成,调用afterSingletonsInstantiated()方法。紧接着执行监听器发送监听后,就会遍历所有的Bean然后初始化所有单例非懒加载的bean。实现DisposableBean当实例bean摧毁时调用destroy()方法。

public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, SmartInitializingSingleton, DisposableBean {
    private static final Logger logger = LoggerFactory.getLogger(XxlJobSpringExecutor.class);


    // start
    @Override
    public void afterSingletonsInstantiated() {

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

        // init JobHandler Repository (for method) 初始化调度器资源管理器
        /**
         * ConcurrentMap<String, IJobHandler> jobHandlerRepository = new ConcurrentHashMap<String, IJobHandler>();
         * handle名; Handler->MethodJobHandler(反射 Object、Bean、initMethod、destroyMethod)
         */
        initJobHandlerMethodRepository(applicationContext);

        // refresh GlueFactory
        GlueFactory.refreshInstance(1);

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

再看super.start()

 public void start() throws Exception {

        // init logpath 初始化日志目录,用来存储调度日志执行指令到磁盘
        XxlJobFileAppender.initLogPath(logPath);

        // init invoker, admin-client 初始化admin链接路径存储集合
        // 在AdminBizClient设置好addressUrl+accessToken
        initAdminBizList(adminAddresses, accessToken);


        // init JobLogFileCleanThread 清除过期日志(30天)
        // 根据存储路径目录的日志(目录名为时间),根据其目录时间进行删除,1天跑一次,守护线程
        JobLogFileCleanThread.getInstance().start(logRetentionDays);

        // init TriggerCallbackThread 回调调度中心任务执行状态
        TriggerCallbackThread.getInstance().start();

        // init executor-server  执行内嵌服务
        /**
         * 1. 使用netty开放端口,等待服务端调用
         * 2. 维护心跳时间到服务端(心跳30S)
         * 3. 向服务端申请剔除服务
         */
        initEmbedServer(address, ip, port, appname, accessToken);
    }

4. 服务注册

在这里插入图片描述

1. 任务执行器

com.xxl.job.core.thread.ExecutorRegistryThread#start

    public void start(final String appname, final String address){
    	...
        registryThread = new Thread(new Runnable() {
            @Override
            public void run() {

                // registry
                while (!toStop) {
                    try {
                        RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), appname, address);
                        // 遍历所有的调度中心
                        for (AdminBiz adminBiz: XxlJobExecutor.getAdminBizList()) {
                            try {
                                ReturnT<String> registryResult = adminBiz.registry(registryParam);
                                if (registryResult!=null && ReturnT.SUCCESS_CODE == registryResult.getCode()) {
                                    registryResult = ReturnT.SUCCESS;
                                    logger.debug(">>>>>>>>>>> xxl-job registry success, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
                          
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值