@emac
2015-11-26T09:39:46.000000Z
字数 3597
阅读 6085
架构
版本:1.1
[术语定义]
任务:如无特殊说明,任务等同于批处理任务 客户端:各类使用BPMS的应用统称,如mobile, web, admin等 系统:指代BPMS
由于一些系统性(系统,网络,应用)的不可靠性,任何一个任务不可避免的存在失败的可能性。当一个任务执行失败时,最简单有效的应对策略就是重新执行,这就要求任务本身具备幂等性,也即多次执行不会产生副作用。
作为第一阶段的目标,系统仅支持业务相关的任务,自定义任务将在后续版本支持。任务在客户端执行,而非系统。
一个任务包含如下属性,由category+name唯一确定:
一条消息包含如下属性,以JSON格式传递:
客户端发送给系统:
系统发送给客户端:
一套高效,可靠的通讯机制是保证整个系统正常运行的基础。根据连接方式的不同可分为基于长连接和基于短连接的两套方案。
为简化系统设计,由客户端保证与系统的连通性。
客户端职责:
系统职责:
客户端发起长连接请求,系统收到请求后,开启一个新的线程维持该长连接,并通过此连接与该客户端的进行双向通讯。
可选框架:
与长连接方式相比,增加心跳检测机制(客户端发起),帮助系统维护一个活动客户端列表。
可选框架:
一个任务可能对应多个客户端,在此情况下,根据其multi属性,调度策略可细化为:
http://www.infoq.com/cn/news/2014/06/qunaer-task-dispatching-center
在使用上我们的任务中心还是挺方便的。因为我们公司大部分Java项目都是基于Spring的,所以我们提供了自定义的Annotation,只需要在你想调度的方法上标记该Annotation,任务就可以自动注册到任务中心里,然后就可以在任务中心的管理后台进行各种参数配置和监控。
任务中心与执行任务的应用之间是通过发消息通信的,这里使用了我们团队自己开发的一个可靠消息中间件。第三方应用作为消息的消费者。任务中心负责调度,当要开始调度一个任务的时候,就往这个应用发送一条消息,第三方应用收到消息后就开始执行任务。
我们默认使用的是随机的负载均衡策略。为了实现高可用,任务调度中心自身也是一个集群,前面也提到执行任务的应用也是集群,而且要保证一个任务同一时刻只有一个实例在运行。当时实现这块儿想到两个方案,一个就是去中心化。任务中心集群的每个节点都可以进度调度,通过协调保证每个任务只有单实例运行。但是这种实现方式虽然看起来很好,但实现还是非常复杂,定位问题也很困难。最后我们选择了中心化的策略。我们利用Zookeeper的选举机制,在任务中心集群里选出一个Leader节点进行任务调度,而其他节点负责心跳跟踪,日志汇总等。当任务调度的节点出现故障,我们可以快速的failover到其他节点上。这样一来整个实现方案就简单得多了,到现在运行有半年多时间,总共有上千的任务在上调度一直工作良好。
http://tech.meituan.com/mt-crm-quartz.html
CRM系统定时任务走过了很多弯路:定时任务多种实现方式,使配置和代码分散在多处,难以维护和监控;任务执行过程没有保证,没有错误恢复;任务执行异常没有反馈(邮件);没有集群支持、负载均衡。CRM系统需要分布式的任务调度框架,统一解决问题,Java可以使用的任务调度框架有Quartz,Jcrontab,cron4j,我们选择了Quartz。