xxl-job 启动浅析

284 阅读3分钟

本文正在参加「Java主题月 - Java开发实战」,详情查看:juejin.cn/post/696719…

这是我参与更文挑战的第9天,活动详情查看: 更文挑战

参考资料

gitee:gitee.com/xuxueli0323…

我们使用的版本是2.1.2,以下源码也是2.1.2的。

连接器部分

准备工作

我们只需要在对应的方法前加上注解:

@XxlJob("jobName")

同时按照以下的方法声明方法签名:

public ReturnT<String> methodName(String params) 

随后在配置文件中指定xxl-job的相关信息,最后在admin中配置即完成任务的配置了。

同时我们需要启动一个admin服务,作为注册的中心。

执行服务

1.连接

我们知道在Spring中,实际上绝大部分第三方组件,都是通过封装成bean,来实现应用启动时启动的。

服务中使用的是Spring,我们可以在

xxl-job-core包下 XxlJobSpringExecutor

中,看到job是如何启动的。

XxlJobSpringExecutor

这个类的类签名如下:

public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, InitializingBean, DisposableBean {

我们可以看出:

  • XxlJob核心的启动器就是XxlJobExecutor了,XxlJobSpringExecutor是这个类在Spring环境下指定的连接器(执行器)。
  • 这个执行器注册到了Spring中。

1.启动代码

启动分为四个步骤,源码如下:

// start
@Override
public void afterPropertiesSet() throws Exception {

    // init JobHandler Repository
    initJobHandlerRepository(applicationContext);

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

    // refresh GlueFactory
    GlueFactory.refreshInstance(1);

    // super start
    super.start();
}

这4个步骤包括:

  • 获取通过 JobHandler注解标识的Bean,并注册。

    • 这个JobHandler是一个标注为*@Deprecated*的注解,现在使用别名 @xxlJob
  • 通过bean,获取bean中通过 JobHandler标识的方法,注册。

  • 刷新GlueFactory,初始化为SpringGlueFactory

    GlueFactory实际上是一个用于创建类的工具

    实际上也就支持默认的和Spring下的

  • 调用父类的start方法。

上面的两个方法实际上就是基本的调用反射来查找配置了的类或者方法,我们接下去看。

1.2 父类start方法

父类中start方法如下:

   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
        port = port>0?port: NetUtil.findAvailablePort(9999);
        ip = (ip!=null&&ip.trim().length()>0)?ip: IpUtil.getIp();
        initRpcProvider(ip, port, appName, accessToken);
    }

这里主要做了如下几个工作:

  • 初始化日志文件的路径,确保日志可以写进去

    • 这个日志也是用的slf4j的包,只是一般配置的日志路径和服务的日志路径不相同,需要单独配置。
    • 如果没有配置,就会使用默认的位置写入。
  • 将配置文件中的admin服务添加到对应的容器中

  • 开启清理日志的线程

  • 开启回调线程

    • 这里需要简单介绍以下xxl-job这部分的回调机制

      实际上在我所在的公司,定时任务部分是不使用回调的,因为日志记录在了不同的地方,查起来也比较麻烦,都是直接在应用日志中排查对应问题的。

      xxl-job任务在执行完毕后,我们会将执行结果返回给注册中心。

      这个结果返回就是通过这个callback线程执行的,它会将执行结果通过post指令发送到注册中心,并打印注册中心处返回的结果。

  • 将本服务注册到admin注册中心上。

到这里就完成了xxl-job执行服务的初始化,包括:

  • 需要job执行的对应代码的保存以及实例初始化

  • 日志路径初始化

  • admin服务在本地注册

  • 初始化日志清理线程,回调处理线程

  • 将本服务注册到admin服务上,并初始化本地的执行器(一般使用默认的,为com.xxl.job.core.biz.impl.ExecutorBizImpl