xxl-job的简单入门
前言
在写这篇文章之前,我们有一个单独的任务调度项目,这个项目按照cron
表达式,隔一段时间执行一下项目的API
。目前来看如果项目不大的话用这种方式也是挺好的,对项目侵入性低,也很灵活。不过由于这个任务调度项目功能过于简单(没有告警,没有页面可以方便的查看日志,权限管理等),也没有足够的文档。所以我们干脆直接找一个开源的分布式任务调度框架。在对比之后选了xxl-job
,看上的是它的轻量和容易上手,而且上述的要求它都能满足。
xxl-job概念
首先先介绍一些xxl-job的概念:
- 调度中心:统一管理任务调度平台上调度任务,负责触发调度执行,并且提供任务管理平台。也就是执行器的触发角色
- 执行器:执行器就是我们需要执行的任务项目了,它由调度中心来负责调用
调度中心搭建
搭建方式有两种,一种是拉取git仓库的源码(SpringBoot项目),修改SpringBoot
的配置文件打包运行就好了
我选的另一种搭建方式,使用Docker
的方式来搭建,先上docker-compose.yml文件,一看基本上就明白了
version: '3.5'
services:
xxl-job-mysql:
image: mysql:8.0
container_name: xxl-job-mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_PASS}
volumes:
- ${VOLUME_PATH}/xxl-job-mysql:/var/lib/mysql
- ./xxl-job.sql:/docker-entrypoint-initdb.d/xxl-job.sql
restart: always
networks:
- kazma_net
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
xxl-job:
image: xuxueli/xxl-job-admin:2.2.0
container_name: my-xxl-job
restart: always
ports:
- 9010:8080
volumes:
- ${VOLUME_PATH}/xxl-job/applogs:/data/applogs
networks:
- kazma_net
environment:
TZ: Asia/Shanghai
PARAMS: "--spring.datasource.url=jdbc:mysql://xxl-job-mysql:3306/xxl_job \
--spring.datasource.username=root \
--spring.datasource.password=pw123456 \
--spring.mail.host=smtp.163.com \
--spring.mail.username=kazma_todo@163.com \
--spring.mail.password="
depends_on:
- xxl-job-mysql
networks:
kazma_net:
name: kazma_network
其中xxl-job.sql
文件是xxl-job官方的sql,需要初始化数据库设置。放入Docker
的docker-entrypoint-initdb.d
目录下,该sql
文件会自动执行,后续初始化后,就不会再执行了。可以参考我的github
配置
另外environment
下的配置也可以参看官方的Dockerfile文件:
FROM openjdk:8-jre-slim
MAINTAINER xuxueli
ENV PARAMS=""
ENV TZ=PRC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ADD target/xxl-job-admin-*.jar /app.jar
ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS /app.jar $PARAMS"]
- 这里把
PARAMS
的参数传递给了项目,具体参数可以参考官方github
上的application.properties
文件` TZ
是写入到了系统的时区上了
这样访问就可以访问了:http://192.168.1.233:9010/xxl-job-admin
,端口是9010
,路径是xxl-job-admin
,界面如下:
默认的用户名是: admin
密码是: 123456
编写执行器
在启动好了调度中心后,会有一个默认的执行器,但是这个只是单纯的配置了,并没实际的代码实现。我们现在就来实现一个,不过我们不会用他这个名字。
新建SpringBoot
项目:
项目依赖如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.2.0</version> </dependency>
主要是
xxl-job-core
这个依赖项目配置如下:
我单纯的把官方的配置转换成了
yml
的格式server: port: 9200 logging: level: root: debug xxl: job: ### 执行器通讯TOKEN [选填]:非空时启用; access-token: admin: ### 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册; addresses: http://192.168.1.233:9010/xxl-job-admin executor: ### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册 appname: demo-job ### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。 address: ### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务"; ip: ### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口; port: 9999 ### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径; logpath: ./applogs/xxl-job ### 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能; logretentiondays: 30
接下来是初始化xxl-job
XxlJobConfig.java
文件package com.xxljob.config; import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; @Component @Configuration public class XxlJobConfig { private static final Logger LOGGER = LoggerFactory.getLogger(XxlJobConfig.class); @Value("${xxl.job.admin.addresses}") private String adminAddresses; @Value("${xxl.job.access-token}") private String accessToken; @Value("${xxl.job.executor.appname}") private String appname; @Value("${xxl.job.executor.address}") private String address; @Value("${xxl.job.executor.ip}") private String ip; @Value("${xxl.job.executor.port}") private int port; @Value("${xxl.job.executor.logpath}") private String logPath; @Value("${xxl.job.executor.logretentiondays}") private int logRetentionDays; @Bean public XxlJobSpringExecutor xxlJobExecutor() { LOGGER.info(">>>>>>>>>>> xxl-job config init."); XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); xxlJobSpringExecutor.setAdminAddresses(adminAddresses); xxlJobSpringExecutor.setAppname(appname); xxlJobSpringExecutor.setAddress(address); xxlJobSpringExecutor.setIp(ip); xxlJobSpringExecutor.setPort(port); xxlJobSpringExecutor.setAccessToken(accessToken); xxlJobSpringExecutor.setLogPath(logPath); xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); return xxlJobSpringExecutor; } }
这里读取了
application.yml
的配置,初始化了一个XxlJobSpringExecutor
对象。真正的任务执行器代码
这其实就是一个
service
@XxlJob("xxl-job-handler") public ReturnT<String> execute(String param) { XxlJobLogger.log("hello world."); return ReturnT.SUCCESS; }
官方解释,我直接摘抄过来了
1、在
Spring Bean
实例中,开发Job
方法,方式格式要求为"public ReturnT<String> execute(String param)"
2、为Job
方法添加注解"@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")"
,注解value
值对应的是调度中心新建任务的JobHandler
属性的值。
3、执行日志:需要通过"XxlJobLogger.log"
打印执行日志;
以上就是整个项目的代码了,可以启动,并且查看日志。
2020-05-16 19:43:22.410 DEBUG 51880 --- [rRegistryThread] c.x.j.c.thread.ExecutorRegistryThread : >>>>>>>>>>> xxl-job registry success, registryParam:RegistryParam{registryGroup='EXECUTOR', registryKey='demo-job', registryValue='http://192.168.1.105:9999/'}, registryResult:ReturnT [code=200, msg=null, content=null]
可以看到本地的任务地址是http://192.168.1.105:9999/
,也就是我们配置的xxl-job
配置上的,不是SpringBoot
项目的9200
端口,这个要注意。然后demo-job
是执行器的名称
配置任务调度中心
配置执行器 重新回到
xxl-job
的任务调度中心web页面
,左侧点击执行器管理,新增一个执行器。这里的AppName
就是我们代码配置的xxl.job.executor.appname
,然后选自动注册就好了。任务管理 点击左侧的任务管理,新增一个任务,具体的解释可以看官方文档
然后在当前任务的右侧点击下拉箭头,单机运行一次,可以在执行器项目的控制台上看到日志的输出,并且在任务调度中心的调度日志上也能看到具体的调用日志。
想要正式的启动,就在任务管理的单个任务上,单机下拉箭头,点击启动即可。后续可以观察日志或者设置告警邮件来检查定时任务的执行过程。
总结
像是邮件告警,权限控制这些我并没有特意的去说明,因为这些太简单了,在界面上点点就能懂。要是有什么疑问也可以看官方的文档解决。
xxl-job
我们也刚开始用,后续如果有什么优化,或者更进阶的使用,我也会用新的文章写上来,总之会把我们现在的任务调度服务给慢慢替换掉
人生苦短,保持简单才是一个项目持久的王道