在分布式系统下,可以很多种架构从事设计,或者分布式系统对技术架构本身没有做严格的限制。但是结合自己的实践以及基于《领域驱动设计》的推荐, 采用 【事件驱动模式】是比较好的一种分布式系统架构方式。该模式充分实现了 不同系统之间的代码解耦,所有的业务流转是通过事件广播进行驱动的。所有业务都是在针对 名为【事件总线】的组件在编程,也无需知道事件的生产者,每个业务只监听自己感兴趣的事件,然后根据事件触发不同的业务代码 以及 自己在处理完某种业务后,也对外广播发出事件,则标志着当前业务的完成。
基于【事件驱动模式】是一种比较接近人类自然行为的一种模式,该模式给系统的解耦以及重构带来了先天优势。相对比与传统的业务模式,大量的业务流程都是基于代码或者是某种规则引擎加以实现,而 事件驱动模式 则是针对事件总线注册监听, 【事件总线】总是能够忠实的把消息投递给感兴趣的监听者,并且保证其对应业务逻辑的自然触发。一旦有业务变动,我们仅仅是在【事件总线】上增加 或者 移除对应的事件消费者,或者注册新的事件发布者,这种行为并没有影响到当前的业务代码变动。 用日常通俗讲法:更加接近于 小学老师讲课,老师常常会不自觉的吼一声:“小朋友们,记住了吗?”这时,这要是听到该咨询的小朋友 都会回应道:“听懂了”,在此过程中 ,声音作为事件、空气作为事件总线(忠实的传递事件到达监听者),如果这个时候,小学的校长在教师边走过,那么老师的咨询同样也被校长听到,但是校长对此不作任何反应,应为该事件对于校长而言,是不关心的事件,所以直接忽略。还是忙他自己的事情。
引入事件驱动,让复杂的系统变得很容易,因为软件就是一直在模仿人类的神经传输,事件驱动是一种比较好的模仿行为。这个时候,大家会问,事件驱动,关键是事件的定义,以及在什么情况下发布事件呢?这个时候 就需要讨论的深入一点,事件是对一种业务行为完成的标识,只有当某一独立的原子业务执行完毕,就要对外发布事件。事件更多的需求术语为:当。。。。。。就该。。。。。。,类似的语境,恰好就是事件驱动完美的体现。 在方法的设计上,我们可以把方法拆分为 读方法 与 写方法,所谓的 读方法就是 该方法内部不对任何数据进行家修改,而是通过一个简单的叠加,组装,把数据有效的输出,而写方法恰好相反,写方法体现在对对象的修改上(并实现最终的持久化操作),所有的事件 是在 写方法中产生。这个以后作为单独的文章描述,为何如此设计呢?为了保证分布式下,数据的一致性等。
一旦引入事件驱动,则事件发布者永远不知道到底有多少消费者在监听该事件,而且当消费者收到事件后,是否正确的处理完其对应的业务,还是中途发生异常呢?事件的驱动是 采用同步方式还是异步方式呢?这就是引入【事件驱动】后,先天不足的一面,所以我们需要在架构上考虑这种不足,通过其他的技术手段来消除这种不足,从而变得稳定可靠。 这样就引出了本文另外一个 所要讲述的话题:长时间过程处理过程的方案,该方案的提出,就是为了解决事件驱动模式下,事件生产者与消费者 在互相不知道对方存在的情况下,而有效的协调完成一个更加的业务呢?
长时间过程处理(业务有专门的术语 称之为 Saga),通过个人的整理以及自己的理解,针对长时间过程处理 一般分为三种解决方案,通过技术手段使得【事件驱动模式】能够更好的为我们服务,三种方案分别如下:
1、把处理过程设计成为一个组合任务,使用一个执行组件对任务进行跟踪,并且对每一个步骤和任务的完成情况进行存储(持久化),然后再根据执行的结果决定是否启动下一个业务环节。该方案更像是责任链模式的灵活应用,缺点是 一开始就需要把该事件 可能触发的子任务进行备案,并对其执行结果进行登记注册,显然,这种方式适合于业务场景比较固定的情况。
2、同第一种方案类似,同样把处理过程设计为一个聚合,聚合成为活动协作的中心,一个或者多个聚合的实例充当之心任务的组件并维护过程中产生的异常等
3、第三种是设计一种 无状态的事件跟踪器,该跟踪器每一个事件的消费者的事件获取与执行情况,并且把执行结果反馈给跟踪器,该跟踪器获取结果后对其进行存储,这样不断的累加事件在消费过程中不断增加的处理结果,这样可以跟踪到事件流转的全部状态,并且按照存储的事件结果,决定是否正常执行完其一个完整的业务,该方案适合于消费者动态的场合,每一次事件的发布,都可以保证到期监听者对事件的消费以及结果的持有,只有当所有事件的状态是正常的,才能确定这个业务是完整的。
三种方案,第二种对代码的耦合度比较大,不建议使用,但是第二种方案是传统编程下最常采用的一种模式。 本人比较倾向于使用 第三种方案, 该方案如同人类神经网络一样,复杂而各司其职。
如果大家要体验这种机制,单机模式 推荐采用 guava 自带的 eventbus作为模拟的事件总线
如果是分布式模式 可考虑引入MQ 中间件作为消息总线。(事件更多的是应用为 P/S) 模式。
另外需要提出的一点是:事件内容能的设计,出了基本类型 就是基本类型,所有的业务事件数据都应当为 某种字符串的展现,如XML、JSON等。。。。。。 另外,事件的发出是有顺序的,这一点也需要引起注意。。。。。
2016年 开年过的有点 纲目不清,还是需要自己多反省,借用王守仁的 心学 “需要在事上下功夫,遇事多磨练自己的内心”。。。。。。