目前任务调度在项目中的问题
- 由于接三方渠道越来越多,越来越多的定制化定时任务
- 目前定时任务没有集中管理,相对比较分散
- 跑批任务现在是单点执行,目前没有做分片执行,其实可以通过mq方式。但是还是存在单点再跑,如果节点没有被调度成功,跑批任务就跪了
业界主流开源
- elastic job(http://elasticjob.io/)
- xxl-job(https://github.com/xuxueli/xxl-job)
- quartz(http://www.quartz-scheduler.org/)
调度项目对比
对比项 | quartz | elastic job | xxl-job |
---|---|---|---|
可用性(HA) | 支持,通过数据库锁方式 | 支持 | 支持通过数据库锁 |
管理台 | 否 | 支持,单不完善 | 支持,功能相对完善 |
分片 | 不支持 | 支持 | 支持 |
社区活跃 | 活跃 | 停止维护几年 | 国内活跃,还在升级维护 |
任务唤醒 | – | 不支持 | 支持 |
任务监控 | 自己扩展 | 不支持 | 支持邮件,调度日志 |
技术复杂性 | 简单 | 相对复杂,需要zookeeper(适合已有zookeeper项目) | 简单,调度中心+执行器(server+client方式) |
调研结果
- 目前公司使用quartz 基于数据库集群模式
- 因为目前公司没有用zookeeper,假如是dubbo项目的话,可能就用elastic-job
- xxl-job 支持任务串行调用
- 社区的活跃程度偏向xxl-job
了解xxl-job
xxl-job 总体分为两个部分调度中心和执行器
xxl-job 调度中心
- 负责任务的调度,不做具体业务的处理
- 存储基于mysql
- 记录调度日志
- 调度器和执行器之间netty通讯,实际还是http
- xxl-job 2.0 版本之后删除了quartz 依赖,具体原因不明,因为quartz依赖只会放到调度中心里,不会在具体执行器里依赖
- 充当执行器注册中心
- xxl-job 调度中心集群,通过数据库锁的方式,避免重复调度,集群是两个完全互补感知的机器,通过nginx upstream + 域名方式来保证可用性
- 为支持不同环境配置及配置集中管理,基于2.1.2 源码集成了nacos配置中心
- xxl-job 定时任务是通过时间轮的方式实现,将快执行的数据放到时间轮里,另外一个线程从时间轮里获取将要执行的任务进行调度,具体原理见图:
xxl-job executor 执行器
- 执行器启动服务时,把包含@jobHandler bean 放到concurrenyMap中
- 注册自己的ip和端口到调度中心
- 启动netty server 为调度中心提供接口调度支持
- 接受调度中心任务调度,从concurrentyMap 中拿去对应任务执行,异步返回调度成功
- 任务执行后,将调度结果回调调度单中心
xxl-job 结构相关图整理
xxl-job 整体类流程图

项目迁移中碰到的问题
- xxl-job 版本 2.1.2 由于2.2.0 升级到了spring boot 2.0,目前项目是1.5.x 所以使用2.1.2
- spring boot 1.5.x 或者说spring cloud 版本中的netty依赖和robbion中的netty依赖冲突,xxl-job 执行器自己实现了netty-server,netty 版本较新,目前robbion没有用到netty,走的http协议,所以把robbion中的netty依赖排除。
- 为了保证不重复执行,任务执行开始和结束都会有分布式锁,测试中发现一个问题,任务如果是分片广播模式,分布式锁是基于任务名称,所以有一台会获取不到锁,这里针对分布式锁,增加了分片信息。
项目部署结构图
