1、为什么要有分布式任务调度?
要想知道为什么会有分布式任务调度,就需要先了解任务调度这个概念,任务调度也可以称为定时任务,简单来说:任务调度(定时任务)就是在某一时刻部署的服务自动执行对应的任务(操作)。
但是对于分布式微服务的部署也同样的会存在一系列的问题:
当然既然存在相对的问题也会有对应的解决方案:
2、调度中心搭建
XXL-JOB源码下载地址:https://github.com/xuxueli/xxl-job
在github上或者gitee上我们可以下载对应xxljob的源码,直接通过maven将多需要的依赖进行安装。
源码结构如下(对于不同版本而言会存在一些出入):
项目包名 | 说明 |
---|---|
xxl-job-admin | 调度中心 |
xxl-job-core | 公共依赖 |
xxl-job-executor-samples | 执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器) |
:xxl-job-executor-sample-springboot | Springboot版本,通过Springboot管理执行器,推荐这种方式; |
:xxl-job-executor-sample-spring | Spring版本,通过Spring容器管理执行器,比较通用; |
:xxl-job-executor-sample-frameless | 无框架版本; |
:xxl-job-executor-sample-jfinal | JFinal版本,通过JFinal管理执行器; |
:xxl-job-executor-sample-nutz | Nutz版本,通过Nutz管理执行器; |
在进行使用的时候我们需要在本地先部署web管理后台,先下载源码,在doc下的db目录下,首先需要创建相对应的数据库跟表。首先启动xxl-job-admin调度中心,我们只需要将这个springboot项目的配置文件当中关于数据库的配置进行修改,修改完成之后直接启动项目。项目启动之后就可以通过配置的默认端口+项目名称进行访问项目了:http://localhost:8088/xxl-job-admin/ 使用默认登录账号 “admin/123456”进行登录
3、SpringBoot集成
在源码当中其实也有一个springboot集成的案例:/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-springboot
而当我们自己搭建springboot项目进行集成时,第一步还是导入xxl-job的核心包:
<dependency>
<groupId>com.xuxueligroupId>
<artifactId>xxl-job-coreartifactId>
<version>2.3.1-SNAPSHOTversion>
dependency>
之后添加相对应的配置,这个可以从前面说的源码的案例当中复制过来,根据本地机器进行相对于的修改。这里只展示xxljob相关配置。
# 调度中心的地址
xxl.job.admin.addresses=http://localhost:8088/xxl-job-admin
### xxl-job, access token
xxl.job.accessToken=
### appname
xxl.job.executor.appname=lzq-job
### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
xxl.job.executor.address=
### xxl-job executor server-info
xxl.job.executor.ip=
// 当端口号为0或者小于0时会采用默认端口9999
xxl.job.executor.port=0
### xxl-job executor log-path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job executor log-retention-days
xxl.job.executor.logretentiondays=30
并且还需要加入一个config配置类,这个可以直接从案例当中复制过来。最后就是编写定时任务了,使用@XxlJob注解用来标识该任务的名称,并且返回的是一个包装类ReturnT,并且可以在这里进行接收调用任务传递过来的参数。
@Component
public class Test {
@XxlJob(value = "Print")
private ReturnT print(String params) {
System.out.println("this is xxl job test");
return ReturnT.SUCCESS;
}
}
到这里定时任务也就编写完成了,之后就是对定时任务的相关配置了,首先添加一个执行器,这里的appname对应的是配置文件当中的appname,对应的机器地址可以使用自动注册,也可以使用手动注册,这里127.0.0.1表示本机地址,端口也是在配置文件当中进行配置的。
第二个就是配置定时任务,这里任务的名称对应的是@XxlJob注解上的名称一致,其余的配置可以根据相对应的业务要求进行配置:
然后就是执行定时任务查看结果了。
4、一致性HASH
在xxljob客户端配置当中有一个路由配置,这里面就提供了一系列的分布式调用任务执行策略。其余的都比较好理解,这里就主要介绍一下这个一致性HASH。这里的一致性HASH主要是用来解决分布式存储结构下动态增减节点带来的问题的解决方案。
首先我们需要知道传统的HASH,传统的HASH主要是对分布式部署的多台机器进行编号排序,获取机器的一个HASH值,通过HASH值对指定数进行取余,将得到的余数作为这个机器的编号。
而这样也存在一定的缺陷:当某一台机器宕机的时候,这时的服务指令就无法分发到指定的机器,这时需要重新对机器的HASH值进行计算编号,之前的编号全部失效,重新计算获取到新的缓存,如果机器分布很多这样的话就很容易会导致缓存雪崩。简单来说:就是不方便来进行动态的增减节点。
一致性HASH对于传统HASH的改变就是,获取HASH值之后对2^32进行取余,获取到所有的节点将其首尾相连构建成一个圆环。之后再对加进来的机器HASH进行取余数,将其固定到圆环上的某一个点。而后续所发生的请求(比如获取业务id)会根据对应的业务id取余数再进行顺时针寻找最近的一个节点机器作为执行该命令的机器。
解决问题:主要解决的是当某一个机器宕机时,只有当前机器所占节点与前一个节点之间的数据需要进行迁移,而其余数据可以不进行处理,解决了一定程度上缓存雪崩的问题。
但是这样的话也会存在一个问题:就是机器节点分布不均的问题,这里一致性HASH引入了一个新的解决方案——虚拟节点,也就是当节点过少时会复制已有的节点作为一个镜像节点,这样做可以使数据分布的更加均匀。