xxl-job源码分析(二):业务接入方启动过程

498 阅读2分钟

一.业务方如何接入

代码参考 xxl-job-executor-sample-springboot项目

1.引入jar包

<!-- xxl-job-core -->
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.3.1</version>
</dependency>

2.往spring中注入一个bean

@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
    logger.info(">>>>>>>>>>> xxl-job config init.");
    XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
    xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
    xxlJobSpringExecutor.setAppname(appname);
    xxlJobSpringExecutor.setAddress(address);
    xxlJobSpringExecutor.setIp(ip);
    xxlJobSpringExecutor.setPort(port);
    xxlJobSpringExecutor.setAccessToken(accessToken);
    xxlJobSpringExecutor.setLogPath(logPath);
    xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

    return xxlJobSpringExecutor;
}

3.配置文件添加

xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
xxl.job.accessToken=default_token
xxl.job.executor.appname=xxl-job-executor-sample
xxl.job.executor.ip=
xxl.job.executor.port=9999

4.编写任务

/**
 * 1、简单任务示例(Bean模式)
 */
@XxlJob("demoJobHandler")
public void demoJobHandler() throws Exception {
    XxlJobHelper.log("XXL-JOB, Hello World.");

    for (int i = 0; i < 5; i++) {
        XxlJobHelper.log("beat at:" + i);
        TimeUnit.SECONDS.sleep(2);
    }
    // default success
}

二.业务方启动流程

从上面可以得知,业务方引入的时候,需要添加bean是XxlJobSpringExecutor,将自己作为一个执行器,后续等待xxl-admin的调用,接下来我们看看XxlJobSpringExecutor这个类做了什么

1.XxlJobSpringExecutor类的继承体系

image.png

2.XxlJobSpringExecutor类的afterSingletonsInstantiated方法

@Override
public void afterSingletonsInstantiated() {

    // 1.初始化 被@XxlJob注解修饰的任务,存放在jobHandlerRepository的一个map中,key=任务的名称,value=任务对应的类-方法
    initJobHandlerMethodRepository(applicationContext);

    // refresh GlueFactory
    // 和glue相关的,不用太专注
    GlueFactory.refreshInstance(1);

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

接下来我们分析这两个核心方法

2-1.initJobHandlerMethodRepository(applicationContext);

概要:这个方法就是扫码项目,找到被@xxljob标识的方法,封装成对象放入一个map中,等待admin的调用

image.png

image.png

2-2.super.start()方法

概要:这个方法就是启动一些线程,启动netty服务端,将自己作为一个执行器注册到xxl-admin上 具体代码如下

image.png

image.png

image.png 接着进入

public void startRegistry(final String appname, final String address) {
    // start registry
    ExecutorRegistryThread.getInstance().start(appname, address);
}

进入start方法

image.png

逻辑比较简单,概括如下

  • 1.如果服务没有停止,就90秒一次,把自己作为执行器调用xxl-admin的/api/registry方法
  • 2.如果服务停止了,就调用xxl-admind /api/remove方法,将自己移除,然后停止这个线程

3.再来看start方法中的 TriggerCallbackThread线程

TriggerCallbackThread.getInstance().start();

image.png

就是从阻塞队列callBackQueue中取出值,调用admin的/api/callback方法,回调结果,callback队列是在哪里存入值?

先说答案,当admin调用执行器来触发定时任务的时候,执行器会里面返回seccess, 然后去开启线程,执行这个任务,并发执行的结果放入callBackQueue阻塞队列中

三.总结

从源码来看,xxl-job的逻辑还是比较简单的,就是spring在启动的时候,会启动netty作为服务端,等待admin调用来触发任务,同时90秒一次将自己注册到admin上,并开启一些其他线程,如回调线程等