本文源码地址:源码地址
说到分布式定时任务,第一反应还是Quartz,毕竟是开源定时任务的大佬。相对来说也比较熟悉,是通过操作API的方式来进行操作。
但是今天我要介绍的是在国内的大佬在Quartz上面增强的的一个分布式定时任务框架:XXL-Job。至于为啥叫这个名字,是因为作者名字叫许雪里。
项目的地址:https://gitee.com/xuxueli0323/xxl-job
下面是大佬提供的Quartz和XXL-job的对比(原文参考:对比)
问题一:调用API的的方式操作任务,不人性化;
问题二:需要持久化业务QuartzJobBean到底层数据表中,系统侵入性相当严重。
问题三:调度逻辑和QuartzJobBean耦合在同一个项目中,这将导致一个问题,在调度任务数量逐渐增多,同时调度任务逻辑逐渐加重的情况加,此时调度系统的性能将大大受限于业务;
问题四:quartz底层以“抢占式”获取DB锁并由抢占成功节点负责运行任务,会导致节点负载悬殊非常大;而XXL-JOB通过执行器实现“协同分配式”运行任务,充分发挥集群优势,负载各节点均衡。
XXL-JOB弥补了quartz的上述不足之处。
下面说下集成思路,我个人比较习惯使用源码集成,下面是大体的starter的项目结构图
首先job-core-provider是直接拷贝的xxl-job-core。这个核心包没有动。
job-admin-center是调度中心
首先配置文件修改:
server:
port: 8666
servlet:
context-path: /xxl-job
#数据源配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/xxl_job?Unicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 10
maximum-pool-size: 30
auto-commit: true
idle-timeout: 30000
pool-name: HikariCP
max-lifetime: 900000
connection-timeout: 10000
connection-test-query: SELECT 1
#邮箱配置
mail:
host: smtphz.qiye.163.com
port: 994
username: [email protected]
password: zwass1314
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
socketFactory:
class: javax.net.ssl.SSLSocketFactory
#MVC配置
mvc:
servlet:
load-on-startup: 0
static-path-pattern: /static/**
resources:
static-locations: classpath:/static/
#freemarker配置
freemarker:
templateLoaderPath=classpath: /templates/
suffix: .ftl
charset: UTF-8
request-context-attribute: request
settings:
number_format: 0.##########
#通用配置,开放端点
management:
server:
servlet:
context-path: /actuator
health:
mail:
enabled: false
#mybatis配置
mybatis:
mapper-locations: classpath:/mybatis-mapper/*Mapper.xml
#XXL-job配置
xxl:
job:
login:
username: admin
password: 123456
accessToken:
i18n: zh_CN
#触发池
triggerpool:
fast:
max: 200
slow:
max: 100
logretentiondays: 30
如果在微服务里面,可以直接注册到注册中心上去,完成权限的统一认证。这里暂时没处理,只是改了几个配置,还是保留单独的验证方式。
job-spring-boot-autoconfigure配置
com.yzc
job-core-provider
${project.version}
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-configuration-processor
true
org.springframework.boot
spring-boot-autoconfigure
核心config配置
@Slf4j
public class XXLJobConfig {
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.executor.appname}")
private String appName;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
log.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppName(appName);
if(StringUtils.isBlank(ip)){
ip = getServerIp();
}
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
return xxlJobSpringExecutor;
}
/**
* 获取本地IP
* @return
*/
private String getServerIp(){
try {
String ip = InetAddress.getLocalHost().getHostAddress();
log.info("Ip:"+ip);
return ip;
}catch (Exception e){
return null;
}
}
}
装配指定
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.XXLJobConfig
这样吧执行器就构造成了一个starter包,在需要引用的服务里面引入starter
com
job-spring-boot-starter
${project.version}
那么构造定时任务有以下2种方式
1、实现接口的方式(已过期,因为一个类不能支出多个定时任务)
@Component
@JobHandler(value = "demoHandler")
public class DemoHandler extends IJobHandler {
@Override
public ReturnT execute(String param) throws Exception {
System.out.println("1111");
return null;
}
}
2、纯注解方式
@Component
public class Demo2Handler {
@XxlJob(value = "demo2Job")
public ReturnT demo2JobHandler(String param) throws Exception{
System.out.println("demo2");
return ReturnT.SUCCESS;
}
}
配置响应的参数
xxl:
job:
admin:
addresses: http://127.0.0.1:8666/xxl-job
executor:
appname: ${spring.application.name}
ip:
port: 9999
accessToken:
启动调度和执行器