GoodJob 分布式远程任务调度框架
写在开头
goodjob 的前身是我在铜板街工作的时候写的 [tongbanjie/legends](https://github.com/tongbanjie/legends) ,那时是在2014年初,我和陈杰(聂风)一起完成了第一个版本。
第一个版本只支持通过HTTP协议,向指定目标服务器发起请求,唤醒指定的一个Job执行,从构思到上线大概也就用了2周多的时间,
后来以及其缓慢的速度在优化迭代,只是公司内部有问题时才会去优化,并且很多代码都是跟公司情况耦合的,能开源出来的不多。
在这4年里也听到了一些声音,说希望能够做的更强大,能够支持的更多,恰巧我最近也些想法,所以准备着手开始 2.0 版本。
具体特性正在梳理,敬请期待,希望能够成为一个对大多数人有用的开源产品, 写于 2018年09月18日晚
v2.0 功能整理
- 触发模式
- 指定时间
- CRON表达式
- 手动触发
- 任务依赖
- 通知模式
- 单台通知
- 群发通知
- 任务选择(单台触发时有效)
- 随机
- 轮训
- 指定
- 通讯协议
-
HTTPv1.0是支持HTTP协议的,但在微服务横行的时代,需要内嵌或外包一个Web容器,或许对系统并不友好 - Socket
- 其他要求
- 同一次触发,不能多次触发
- 触发要保证稳定性,支持多机集群
- 记录任务执行过程、结果、耗时
- 支持任务中断,依赖任务实现支持
- 支持任务异常报警、超时报警、未执行报警
看起来2.0应该是完全不向下兼容的
Trigger Server 集群能够解决的问题
- 单台 Trigger 如果挂了,任务就触发不了了,有单点风险
- 单台 Trigger 容量、计算能力有限,集群部署做任务分区可以提高任务规模
关于 Trigger Server 集群时,只允许有效触发一次的思考
集群环境,如何保证 Trigger Server 多节点时,任务触发只会触发一次呢?
Quartz 集群是靠数据库悲观锁做的,而且在任务执行过程中一直占有锁;
但我们系统不能这么设计,首先不能为了占有锁而一直 hold 线程,如果用分布式锁也会涉及到任务并发执行而执行不了的问题;
任务并发执行是指任务耗时较长,间隔较短,导致同一个任务在同一时间,有多个线程在执行,而非一次触发了多次;
为了能够并发执行,所以不能一直获取着某个任务的锁,否则下一次的触发可能会导致任务无法正常执行;
但某个 Trigger Server 从获取锁 -> 唤醒任务 -> 释放锁的过程是很快的,释放锁之后,其他的 Trigger Server 可能只阻塞了1秒不到的时间
如何判断2台Trigger Server 是同一次的触发呢?
- 约定个间隔,比如10秒钟或1分钟内都视为同一次触发,不能再次执行;
- 选举出一个 Leader ,由 Leader 来统一调度,其他服务只做热备份不工作;
之前在 v1.0 版本里,采用的是 方案1
,考虑到这样更能发挥各个机器的性能,手动触发不会被频率限制
关于 Trigger Server 集群时,任务信息同步的思考
任务信息都是需要加载到内存中的,当任务信息有变化时,让各个 Job Server 同步是一件比较麻烦的事, 这个没想到好的办法,只能定一个时间间隔,不断的加载到内存,刷新任务信息
关于群发通知/任务切片的思考
群发通知,是为了通知所有 Job Server 要干活了,各个 Job Server 如何分工,我认为任务调度框架是不管的,也不知道该怎么管。
但不代表任务调度框架什么都不做,至少应该要告诉 Job Server ,总共有多少个 Job Server ,你是其中的第几个。
这样业务开发可以将逻辑维护在 Job Server 中的 Job 里,根据传入的信息来各自进行工作,任务如何切片,在 Job 中自行维护。