分布式任务调度平台xxl-job

一.java的集中式任务调度

  1. while(true) + Thread.sleep
    轮询 + 线程休眠的方式实现定时任务
  2. java.util.Timer + java.util.TimerTask
    Timer是一种定时器工具,用于使用后台线程计划执行指定任务,它可以指定执行一个任务一次或多次
    TimerTask是一个抽象类,他的一个子类代表一个可以被Timer计划的任务。
  3. ScheduleExecutorService
    ScheduleExecutorService是从jdk1.5开始作为并发工具类被引入的,是最理想的定时任务实现方式。
  4. Quartz
    Quartz是一个开源的定时任务调度框架,由java编写而成,用于java生态下的定时任务调度,是一个灵活方便、使用简单的定时任务调度框架,可以和Spring整合使用。
  5. Spring Task
    Spring框架提供的轻量级的定时任务调度工具,使用方便
  6. Spring Boot注解@EnableScheduling + @Scheduled
    底层依然采用Spring Task

集中式调度的问题:
分布式集群的模式下,如果采用集中式的任务调度方式,会带来一些问题,比如:

  • 多台机器的集群部署的定时任务如何保证不被重复执行?
  • 如何不重新部署动态的调整定时任务的执行实践?
  • 部署定时任务的机器发生故障如何实现故障转移?
  • 如何对定时任务进行监控?
  • 等等…

解决方法:

  • 使用数据库唯一约束
  • 使用配置文件、redis、mysql作为调度的开关
  • 使用分布式锁来实现调度的控制
  • 使用分布式任务调度平台TBSchedule、Elastric-job、Saturn、xxl-job、Google Cron系统

二.分布式任务调度平台xxl-job

XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
github地址:https://github.com/xuxueli/xxl-job/

xxl-job整体架构:
分布式任务调度平台xxl-job_第1张图片

1.xxl-job源码结构介绍

下载xxl-job源码并解压后,用idea打开
可以发现整个项目有

  • xxl-job-admin:调度中心
  • xxl-job-core:所需要的工具类,admin依赖于core项目
  • xxl-job-executor-samples:使用案例

三个子项目

2.xxl-job分布式任务调度平台实践

调度中心创建:

  • 从github上获取源码
  • 从源码中得到SQL脚本创建和初始化数据库
  • Maven编译打包xxl-job-admin并部署为调度中心
  • 启动运行xxl-job-admin,并访问http://localhost:8080/xxl-job-admin

执行器向调度中心注册:

  • 创建执行器(具体调度地址),可以支持集群
  • 配置文件需要填写xxl-job注册中心地址,支持集群,用","分割
  • 每个具体执行的job服务器都需要创建一个netty连接端口号
  • 需要执行的任务方法,使用@XxlJob注解进行标注
    • 在项目启动时,执行器会通过“@XxlJob”识别Spring容器中“Bean模式任务”,以注解的value属性为key管理起来。
  • 方法中编写具体的job任务

(1)调度中心启动

在运行之前我们需要先更改xxl-job-admin项目中的application.properties配置文件,配置自己的数据库、邮箱、token等。

xxl-job从2.2.0开始就将数据库连接池换为了springboot2.0默认的hikari

使用sh mvnw.sh clean package -DskipTests打包之后运行

1. 更改pom文件中的artifactId

2. 复制run文件
	更改run/service.sh中的serviceName和targetName
	[删除logback.xml文件,logback-spring.xml不需要改,但是需要在application.properties中添加LOG_HOME配置
	logback和logback-spring.xml都可以用来配置logback,但是2者的加载顺序不一样
	logback.xml加载早于application.properties
	所以如果你在logback.xml使用了变量时,而恰好这个变量是写在application.properties时,那么就会获取不到,只要改成logback-spring.xml就可以解决。]
	
3. 复制mvnw.sh文件
	之后构建jar包使用sh mvnw.sh clean package -DskipTests进行构建

4. 更改dockerfile文件
	更改基础镜像,下载通用包
	COPY jar包和运行脚本.sh文件
	更改容器运行命令

5. 更改application配置文件更改,新增application-dev和application-prod文件
	注意spring.profiles.active应改为spring.config.activate.on-profile,但启动命令中的不变
	为dev,prod配置数据库地址,数据库名字我们也可以改,不需要建新的数据库,注意在数据库地址那里加上时区属性防止乱码
	更改server.servlet.context-path=/xxl-job-admin
	
6. 注册中心的账号和密码请直接更改数据库或.sql文件(密码需要md5加密后插入)


PS:任务调不通可能是由于netty的问题

(2)执行器整合xxl-job

1. 项目中引入依赖
	maven:
		
            com.xuxueli
            xxl-job-core
            2.3.1
        
	gradle:
		compile 'com.xuxueli:xxl-job-core:2.3.1'
		
2. 更改application配置文件
	增加xxl-job的相关注册配置

3. 增加xxl-job配置类XxlJobConfig
	
4. 在要注册的任务上添加@XxlJob注解
	这样才能在xxl-job-admin中看到
	
jar包冲突:
	java.lang.NoClassDefFoundError: com/xxl/job/core/executor/impl/XxlJobSpringExecutor
	将依赖改为compile方式

重要的几个配置:
xxl.job.admin.addresses:配置任务调度中心的地址。不用担心配置的是集群虚拟ip导致执行器只在一台机器上注册,我们的执行器注册信息是存放在数据库表中,这个项目只是用来定时发送调度请求的。
xxl.job.executor.ip:执行器的地址
xxl.job.executor.port:执行器的端口,这个端口和服务的端口需要分开。
服务的端口指的是外部访问通过哪个端口进行访问,而高贵的调度中心需要新的端口发送调度请求给项目。所以我们还需在容器那里暴露该端口供调度中心连接项目发送请求。
后面这两个需要自动注册的时候配,手动注册可以不用配

  • XXL-JOB会为每次调度请求生成一个单独的日志文件,通过 “XxlJobHelper.log” 打印执行日志
  • 这些日志文件就放在xxl.job.executor.logpath指定的目录下。
  • “调度中心”查看执行日志时将会加载对应的日志文件。

三.项目整合xxl-job遇到的问题

1.执行器手动注册,调用不通

错误信息:xxl-job remoting error(no protocol: xxx/run), for url : xxx/run
解决:
no protocol表示我们地址没加连接协议,在手动注册的地址前加上"http://"

2.执行器地址加上连接协议http后仍调用不通

**错误信息:xxl-job remoting error(connect timed out), for url : **
解决:
连接执行器超时,请检查对应的服务端口是否打开

3.执行器自动注册和回调都失败,但是调用成功

错误信息:

注册失败报错信息:
xxl-job registry fail, registryParam:RegistryParam{registryGroup='EXECUTOR', registryKey='system-executor', registryValue='http://x.x.x.x:xxxx/'}, 
registryResult:ReturnT [code=500, msg=xxl-job remoting fail, StatusCode(307) invalid. for url : http://xxl-job-admin-test.com/api/registry, content=null]
 
回调失败报错信息:
xxl-job job callback fail, callbackResult:ReturnT [code=500, msg=xxl-job remoting fail, StatusCode(307) invalid. forurl : http://xxl-job-admin-test.com/api/callback, content=null]

解决:
查看日志发现注册和回调都失败了,但是调用是执行成功的
调用成功说明admin能够访问执行器,但是执行器注册失败,表示执行器访问不了admin
怀疑是xxl.job.admin.addresses配置的有问题,xxl.job.admin.addresses配置的是inner域名,改为ip:port就可以访问成功了
推测:
项目和admin属于同一网段,即使不使用域名也是可以直接用ip:port进行访问的,而公司内部的inner域名应该是只允许公司内部网网段进行访问的,因此用inner反而访问不通了

4.任务调度中心admin报错,数据库连接失效

错误信息:HikariCP - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl
解决:
数据库的默认超时时间为500s,但是xxl-job-admin中spring.datasource.hikari.max-lifetime=900000
因此数据库连接池中的连接还没断开,但已经超过数据的连接超时时间了
把spring.datasource.hikari.max-lifetime=400000即可解决

你可能感兴趣的:(知识分享,分布式,java,spring)