好多年前公司就用xxl-job了,最近自己搞了下,执行器使用的一个.net库。坑挺多的,目前看xxl-job还是个人维护的,总有不完善的地方。记录下,也作为自己的总结。
一、调度中心
我用Docker镜像方式搭建的。
1,pull镜像的坑
一般镜像都用latest标签标记最新版本,Docker默认也是拉取打了latest标签的版本。但是xxl-job调度中心镜像没有打这个标签,所以只能拉取指定标签。
看https://github.com/xuxueli/xxl-job/ Releases最新版本是2.4.0,猜测镜像标签也是2.4.0。果然。
2,xxl.job.accessToken的坑
xxl.job.accessToken默认不是空,默认是“default_token”。详情见 xuxueli/xxl-job@390165d
下面是我启动容器的命令,注意每个PARAMS配置项都需要“--”开头。也可以通过修改配置文件的方式指定参数,参见我同事的文章
docker run -e PARAMS="--spring.datasource.url=jdbc:mysql://XXXX:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai --spring.datasource.username=root --spring.datasource.password=123456 --spring.mail.username=XXXX --spring.mail.password=XXXX --xxl.job.accessToken=XXXX" -p 8080:8080 -v /tmp:/data/applogs --name xxl-job-admin -d --restart=always xuxueli/xxl-job-admin:2.4.0
二、执行器项目
1,执行器是什么的坑
看调度中心中执行器是一个模块,任务是一个模块,并且任务可以自由选择执行器。让人不禁以为执行器和任务是完全解耦的,是两个东西。自己还以为执行器把任务拉到自己服务器上执行呢。搜了几篇xxljob原理的文章,逐渐明白了。下面是讲的比较好的两篇,推荐全文阅读,对xxl-job会有更深入的了解。
https://cloud.tencent.com/developer/article/2367296
https://zhuanlan.zhihu.com/p/36627346
看完终于知道“任务就是你要执行的业务代码,函数。执行器就是任务所在程序部署的服务。”
那么任务和执行器必然是在一起的。那么为什么任务可以选择不同执行器呢?是因为同一套执行器代码部署多台服务器的时候,指定成不同的执行器,就可以实现在不同机器上执行不同任务。比如一套代码里有任务A,任务B,我可以发布到两台机器上分别配置成执行器a ,执行器b。那调度中心我可以任务A选择执行器a,任务B选择执行器b。一套代码不同配置(要注册成两个执行器),一台机器上永远执行任务A,一台机器上永远执行任务B。任务A需要大内存,任务B需要大网络流量,就可以针对性的配置服务器。
任务并不能任意选择执行器,只能选择包含这个任务的执行器。
2,执行器实现的坑(.net实现)
.net 实现xxl-job执行器,星星最多的是https://github.com/xuanye/DotXxlJob。并且目标框架是.NET Standard。还提供了一个案例,可以直接用来测试。
坑1:配置adminAddresses 不能要url最后的"/",
坑2:调度中心xxl.job.accessToken默认值是“default_token”了,注意配置。
坑3:执行器注册成功,但是调度中心不显示执行器。这里有解释:https://github.com/xuanye/DotXxlJob/issues/6,
“在admin后台录入一个执行器,选择自动注册,(其实是添加一类执行器)。
然后再执行器配置对应的appName 就能实现执行器的自动注册 (注册具体的机器)”
说好的自动注册就这?是执行器实现的问题还是xxl-job就这么设计的呢?
官方文档中执行器注册提交的内容如下
{
"registryGroup":"EXECUTOR", // 固定值
"registryKey":"xxl-job-executor-example", // 执行器AppName
"registryValue":"http://127.0.0.1:9999/" // 执行器地址,内置服务跟地址
}
没有指定执行器名称的地方。所以应该是xxl-job就这么设计的。
可以修改下源码,在注册执行器的地方加下控制台输出或者日志,就能知道注册执行器提交的内容和返回内容了。
注册执行器的时候,没有对应AppName的执行器(控制台中的执行器),竟然也能注册成功,也算一个坑吧。
下面是几点需要注意的。
1,一套执行器代码部署多台服务器,但是使用同一个appname就可以注册到一个执行器(控制台中的执行器)中实现负载。每次任务执行的时候,首先会根据这个任务找到对应的执行器(控制台中的执行器),根据一些路由的策略选中一台机器,触发执行器的任务执行。
2,调度中心调用执行器走http协议,所以执行器服务需要部署为一个Http服务
3,分片广播,每个执行器怎么知道只执行自己的部分?
调度中心知道一个执行器有几个实例,会告诉每个实例当前执行器的分片序号和分片总数。jobhandler中能拿到这两个参数,然后自己写代码实现。