【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理

文章目录

  • 1. 概述
  • 2. 调度关系
  • 3. 执行器注册
    • 3.1. 调度中心处理注册请求
    • 3.2. 执行器发起注册请求
  • 4. 执行器注销
    • 4.1.主动注销
    • 4.2. 被动注销
  • 5.流程图
  • 6. 总结

1. 概述

通过前面两篇文章《调度中心集群配置》《执行器配置及定时任务的创建》,我们已经获取到了一个XXL-JOB的集群,以及一个可以执行任务的调度器,在实际的项目中可以参照这个流程,引入定时任务。
接下来,我们就可以来探索一下执行器的注册与发现的原理了,本篇主要是描述执行器的注册与发现,主要包括以下几点内容:

  • 执行器注册
  • 执行器的注销
  • 调度器探活

这几个机制共同构成了一个稳定运行的定时任务流程。

2. 调度关系

一个定时任务的方法是如何被调用的呢?
XXL-JOB的调度关系分为了3层,每层向下进行调度,最上层是调度中心,最下层是定时任务方法,调度中心可以调度不同的执行器,执行器再调用归属于自己的定时任务,如下图所示:
【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第1张图片
调度中心在调度执行器时,需要知道执行器的ip和端口号,以此来找到对应的执行器节点来进行调度。而调度中心获取到执行器ip的方式有两种,分别是:自动注册、手动录入
一般不会使用手动录入的方式,可以想象一下,新增、减少了执行器实例,执行器宕机需要下线都需要手动修改机器地址,意味着需要有人24小时盯着,这是一件很可怕的事。
所以,正常情况下我们都会选择使用自动注册的方式来创建,选择这种方式的话,就需要调度中心与执行器之间建立通信机制,通过网络请求传输注册信息。

注:下面是在后台管理系统中的配置。
【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第2张图片

3. 执行器注册

当前版本(2.3.1)的XXL-JOB采用的是Http通信,而调度中心是通过SpringBoot来实现的。
因此可以猜测,调度中心就是启动了一个Tomcat,并提供了执行器注册接口,执行器在启动的时候,将自己的ip,端口等信息传输到调度中心,由调度中心存起来,这样就完成了执行器注册。

3.1. 调度中心处理注册请求

首先,需要调度中心向外暴露注册接口才能收到执行器的注册请求。
在调度中心新的服务xxl-job-admin中,我们可以查看contoller包中是否提供了注册的接口,XXL-JOB的命名比较规范,我们可以很容易的找到一个api相关的Controller接口JobApiController
果然,在这个类里面有一个api相关的方法,如下:
【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第3张图片
一路顺藤摸瓜,就找到了实际做注册动作的方法:
【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第4张图片
注意截图中的3个红框,这里包含了两个关键点:

  • getXxlJobRegistryDao():表示操作的是xxl_job_registry这张表。
  • registrySave和registryUpdate:先更新执行器信息,如果更新失败了,就创建一条执行器注册数据。

简单的说,就是调度中心会接收执行器的registry请求,然后将请求中传入的参数保存到xxl_job_registy表中。这就是调度中心运行的执行器注册主流程,一个非常简单的CRUD。
看完了主流程之后,我们再来看一下细节,可以发现这里的注册代码并不是同步执行的,而是通过一个线程池registryOrRemoveThreadPool来进行的异步操作。这里也提现了XXL-JOB的一个设计思想,即全异步化调用,我们在研究后续原理的时候,还会经常看到这样的用法。

注册或注销线程池的创建
registryOrRemoveThreadPool这个线程池在这里可以直接使用,那一定是提前创建好的,有两种方式可以找到创建这个线程池的位置。

  • 第一种:通过Idea的usages可以找到new ThreadPoolExecutor()的地方,这就是线程池的创建。
    【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第5张图片
  • 第二种:可以通过配置过程分析,全局搜索properties配置的key,查看是哪个位置使用了properties的值,再去找afterPropertiesSet方法,一般的初始化都会在这个方法中。
    【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第6张图片
    显然,初始化方法就是这里的init(),因为XXL-JOB的命名是比较规范的,我们很容易就可以找到线程池初始化的位置。
    【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第7张图片
    点进去之后可以发现,在start()方法中除了初始化registryOrRemoveThreadPool之外,还启动了一个线程registryMonitorThread这个线程就是调度中心的探活线程,下面的注销原理中会提到。

上面详细的描述了如何在源码中找到对应的方法位置,以及调度中心处理注册请求的过程,忽略探活线程的流程如下:
【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第8张图片

3.2. 执行器发起注册请求

我们所说的执行器,实际上就是一个普通的Spring-Web项目,在其中引入了xxl-job-core包,按照上面描述的源代码查询流程,通过properties文件可以定位到执行器对象XxlJobSpringExecutor,在这个对象中对执行器做了初始化的操作。
由于篇幅的关系,下面就不再贴代码了,而是描述整个流程。

我们可以通过注册信息,倒推一下执行器做了什么,下图是调度中心保存的一个执行器的注册请求数据。
【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第9张图片

  • 执行器需要获得调度中心的地址,才能够发起Http请求,这个地址是配置在properties文件中的。同时,在数据行中的registry_key字段值也可以通过properties配置文件中配置直接获取。
  • registry_value中的ip和端口信息,也可以来自配置文件,只是还需要做一点额外的操作。既然是将ip和端口号信息传输到了注册中心,其目的肯定是希望调度中心通过这个ip和端口号来调度执行器执行定时任务,也就是说,执行器在启动时,也会向外暴露一个Http接口,这个接口会用于后面的定时任务调度。

也就是说,执行器这边的主要流程就3个,如下图所示:
【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第10张图片

4. 执行器注销

执行器的注销分为主动注销被动注销两种。

  • 主动注销:顾名思义,就是执行器向调度中心发送注销请求,调度中心接收后把这个执行器的注册信息删除掉。
  • 被动注销:就是执行器以外宕机后,无法正常的向调度中心发送注销请求,由调度中心的探活线程发现了某个执行器已下线,此时将该执行器的注册信息删除掉。

4.1.主动注销

主动注销的发起时机是在Spring容器正常关闭时,XXL-JOB的执行器类实现了DisposableBean接口,这个接口会在Spring的停止流程中被调用,此时会调用registryRemove接口。
调度中心收到请求后,也会通过registryOrRemoveThreadPool线程池进行异步处理,最终将xxl_job_registry中对应的执行器信息删除掉。

这个过程与注册的过程类似,这里就不过多的赘述了。

4.2. 被动注销

前面我们看到了在调度中心初始化时,会启动一个探活线程registryMonitorThread,这个线程每30秒会执行一次,执行时会查询xxl_job_registryupdate_time与当前时间的差值大于90s的数据,将这部分数据给删除掉。
在这里插入图片描述
也就是说,某个执行器在90秒至120秒内都没有发送新的注册请求来维持心跳的话,这个执行器就会被调度中心干掉。

心跳是怎么维持的呢?
在上面3.1中的代码截图中,我们可以看到,注册接口实际上是做了保存和更新两种处理,这里的更新方法其实就是在更新update-time的值,目的就是为了维持心跳,不被探活线程给干掉。
【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第11张图片
在执行器所在的服务中,也有一个线程在不断的请求注册接口来更新注册信息,具体位置在ExecutorRegistryThread类中,创建了一个registryThread线程,每30秒会调用一次registry接口,直到服务停止。

5.流程图

经过上面的探索,我们已经了解了执行器的注册与注销的流程,下面是这整个流程的流程图。
【分布式任务调度】(三)XXL-JOB的注册与发现流程及原理_第12张图片

6. 总结

本篇内容主要是在探索执行器注册到调度中心的流程及实现原理。

  1. 调度中心启动了一个Tomcat作为Web容器,暴露出注册与注销的接口,可以供执行器调用。
  2. 执行器在暴露了调度接口后,将自己的ip、端口信息通过调度中心的注册接口传输到调度中心,同时每30秒会调用一次注册接口,用于更新注册信息。
  3. 同理,在执行器关闭的时候,也会请求调度中心的注销接口,进行注销。
  4. 调度中心在接收到注册或注销请求后,会操作xxl_job_registry表,新增或删除执行器的注册信息。
  5. 调度中心也会启动一个探活线程,将90秒都没有更新注册信息的执行器删除掉。

注:本篇只是在探索注册于发现的流程,所以忽略在这个流程中还涉及到的任务调度与回调相关的逻辑。

你可能感兴趣的:(分布式中间件,分布式,java,XXL-JOB)