1 背景
兼容技术团队自研的RPC框架,技术团队不需要修改代码,RPC注解方法可以托管在任务调度系统中,直接当做一个任务来执行。
研读XXL-JOB,同时从阿里云分布式任务调度 SchedulerX 吸取。
SchedulerX 1.0 架构图
- Schedulerx-console 是任务调度的控制台,用于创建、管理定时任务。负责数据的创建、修改和查询。在产品内部与 schedulerx server 交互。
- Schedulerx-server 是任务调度的服务端,是 Scheduler的核心组件。负责客户端任务的调度触发以及任务执行状态的监测。
- Schedulerx-client 是任务调度的客户端。每个接入客户端的应用进程就是一个的 Worker。Worker 负责与 Schedulerx-server 建立通信,让 schedulerx-server发现客户端的机器。并向schedulerx-server注册当前应用所在的分组,这样 schedulerx-server才能向客户端定时触发任务。
我们模仿了SchedulerX的模块,架构设计如下图:
选择 RocketMQ 源码的通讯模块 remoting 作为自研调度系统的通讯框架:阅读 SchedulerX 1.0 client 源码中,发现 SchedulerX 的通讯框架和RocketMQ Remoting很多地方都很类似。它的源码里有现成的工程实现。
将 RocketMQ remoting 模块去掉名字服务代码,做定制。
在RocketMQ的remoting里,服务端采用 Processor 模式。
调度中心需要注册两个处理器:回调结果处理器CallBackProcessor和心跳处理器HeartBeatProcessor 。执行器需要注册触发任务处理器TriggerTaskProcessor 。
public void registerProcessor(
int requestCode,
NettyRequestProcessor processor,
ExecutorService executor);1.2.3.4.
处理器的接口:
Explainpublic interface NettyRequestProcessor {
RemotingCommand processRequest(
ChannelHandlerContext ctx,
RemotingCommand request) throws Exception;
boolean rejectRequest();
}1.2.3.4.5.6.
对于通讯框架来讲,我并不需要关注通讯细节,只需要实现处理器接口即可。
以触发任务处理器TriggerTaskProcessor举例:
搞定网络通讯后,调度器如何设计 ?最终我还是选择了Quartz 集群模式。主要是基于以下几点原因:
- 调度量不大的情况下 ,Quartz 集群模式足够稳定,而且可以兼容原来的XXL-JOB任务;
- 使用时间轮的话,本身没有足够的实践经验,担心出问题。另外,如何让任务通过不同的调度服务(schedule-server)触发, 需要有一个协调器。于是想到Zookeeper。但这样的话,又引入了新的组件。
- 研发周期不能太长,想快点出成果。
自研版的调度服务花费一个半月上线了。系统运行非常稳定,研发团队接入也很顺畅。调度量也不大 ,四个月总共接近4000万到5000万之间的调度量。
自研版的瓶颈,我的脑海里经常能看到。数据量大,我可以搞定分库分表,但 Quartz 集群基于行级锁的模式 ,注定上限不会太高。
2 实战
- 去掉外置的注册中心,调度服务(schedule-server)管理会话;
- 引入zookeeper,通过zk协调调度服务。但是HA机制很粗糙,相当于一个任务调度服务运行,另一个服务standby;
- Quartz 替换成时间轮 (参考Dubbo里的时间轮源码)。
这个Demo版本在开发环境可以运行,但有很多细节需要优化,仅仅是个玩具,并没有机会运行到生产环境。
最近读阿里云的一篇文章《如何通过任务调度实现百万规则报警》,SchedulerX2.0 高可用架构见下图:
文章提到:
每个应用都会做三备份,通过 zk 抢锁,一主两备,如果某台 Server 挂了,会进行 failover,由其他 Server 接管调度任务。
这次自研任务调度系统从架构来讲,并不复杂,实现了XXL-JOB的核心功能,也兼容了技术团队的RPC框架,但并没有实现工作流以及mapreduce分片。
SchedulerX 在升级到2.0之后基于全新的Akka 架构,这种架构号称实现高性能工作流引擎,实现进程间通信,减少网络通讯代码。
在我调研的开源任务调度系统中,PowerJob也是基于Akka 架构,同时也实现了工作流和MapReduce执行模式。
3 技术选型
首先我们将任务调度开源产品和商业产品 SchedulerX 放在一起,生成一张对照表:
Quartz 和 ElasticJob从本质属于框架。
中心化产品从架构上来讲更加清晰,调度层面更灵活,可以支持更复杂的调度(mapreduce动态分片,工作流)。
XXL-JOB 从产品层面已经做到极简,开箱即用,调度模式可以满足大部分研发团队的需求。简单易用 + 能打,所以非常受大家欢迎。
其实每个技术团队的技术储备不尽相同,面对的场景也不一样,所以技术选型并不能一概而论。
- 幂等。当任务被重复执行的时候,或者分布式锁失效的时候,程序依然可以输出正确的结果;
- 任务不跑了,千万别惊慌。查看调度日志,JVM层面使用Jstack命令查看堆栈,网络通讯要添加超时时间 ,一般能解决大部分问题。
参考
- https://xie.infoq.cn/article/ca1973d9c00fae8a747fd5b9f
- https://www.51cto.com/article/707369.html