ENode 2.6 架构与设计简介以及全新案例分享

前言

ENode是一个应用开发框架,为开发人员提供了一整套基于DDD+CQRS+ES+EDA架构风格的解决方案。ENode从发布1.0开始到现在的差不多两年时间,我几乎每周都在更新设计或实现代码。以至于从来没有一个稳定的版本可以提供给大家,非常惭愧。但我相信,随着时间的推移和我的努力的积累,ENode一定会越来越稳定和成熟的。我觉得我此刻很幸福,因为我有自己的兴趣且有机会在业余时间为了自己的兴趣而奋斗。

ENode开源地址:https://github.com/tangxuehua/enode

今天是个开心的日子,因为我终于使用ENode开发出了一个比较有说服力的真实案例,一个在线会议位置管理与订购系统。该案例与微软的Microfost CQRS Journey案例的功能一致,只是是用ENode开发完成的。目的是为了展示:

  1. 如何使用ENode支持DDD领域层的实现;
  2. 如何使用ENode实现CQRS+ES的架构;
  3. 如何使用ENode实现事件驱动的架构(EDA);

另外,在案例开发过程中,也不断发现了ENode, EQueue的很多问题。所以,通过做这个案例,也帮助ENode, EQueue完善了很多。真是要实践才能进步啊!

ENode架构简介

ENode目前的架构已经和最初的1.0版本有较大的差别了。比如,没有了对Redis的依赖,增加了Command Store的设计。最新版本的ENode架构图如下:

熟悉CQRS架构的人应该对这个图不太陌生。需要强调的有两点:

  1. 新版的架构图中,Domain Aggregate是常驻内存的;聚合根的职责就是封装状态、业务规则,同时产生领域事件;
  2. 新增了一个Command Store,用于实现Command的幂等处理;

关于图中的其他部分的介绍,请参看我之前写的关于ENode系列的文章。 

ENode关键特性

  1. 实现了CQRS架构,支持分布式,基于队列的水平扩展,框架设计之初就考虑了架构的各个节点的水平扩展;
  2. 面向高并发设计;架构层面,充分考虑到了如何解决并发问题;通过用EQueue实现服务器之间的消息路由、通过单机内部实现类似Actor Mailbox的设计,从而避免并发的产生。提高CQRS架构C端的整体写入吞吐量;即便在某些极端情况下出现并发问题,也支持自动的乐观检测,并自动重试;另外,架构层面,规定一个command只能涉及一个聚合根的修改,从而规范应用开发者必须严格按照消息驱动的思路来实现复杂的业务流程,而不能使用工作单元的方式,以事务的方式实现数据的强一致性;
  3. 严谨的消息幂等处理支持;由于ENode是消息驱动的架构,所以对消息的幂等性处理,是框架关注的一个重要的方面,并在架构层面做了支持。这使得应用开发人员不必担心消息的重复处理带来的问题。
  4. Domain Aggregate常驻内存;这个设计可以提高C端command的处理性能。因为我们不必像传统的方式那样先把聚合根从db取出来,再修改,再保存回去了;
  5. 框架为开发人员展示了如何更好的实现Sagas,在CQRS架构中,Sagas指基于消息驱动的业务流程;一个Saga包含若干个聚合根以及一个(通常)流程管理器(Process Manager);聚合根维护流程中的所有参与者对象的状态以及流程本身的状态,流程管理器负责定义和实现流程控制逻辑,无状态;流程管理器的实现是通过响应事件、异常、应用层消息,然后发送相应的命令,从而实现消息驱动的流程;
  6. 采用Event Sourcing(简称ES)的方式来持久化聚合根状态;通过ES实现聚合根状态的还原以及通用的并发控制,通过聚合根ID+事件版本号作为唯一索引的思路实现乐观并发控制;
  7. 消息除了command, domain event外,还支持exception message, application message;这两种消息是我们在遇到有些消息不适合用domain event来表达时需要使用到;比如聚合里有时我们要修改某个状态前会先做业务规则的检查判断,如果不合法,通常会抛异常,然后这个异常我们又希望可以让流程管理器知道,从而流程管理器可以做后面的回滚或补偿措施;另外,我们有时可能会在应用层面(command handler里)和其他外部系统发生交互,那交互的结果,使用应用层的消息更合理;ENode在架构层面,对上面这些消息做了统一的支持;
  8. 框架提供返回单个command执行结果以及阻塞等待command执行结果的支持,这个对于开发者希望同步执行command并知道command执行结果的时候,非常有帮助;这样开发者就不用自己去轮训了。
  9. 除了对消息的幂等处理的支持外,ENode对domain event的顺序处理,也做了充分的考虑和支持,确保当C端产生的domain event同步到Q端时,Q端处理时,框架层面能确保Q端的处理顺序不会乱序。从而保证C,Q两端的数据是最终一致的;
  10. 保证消息能至少被处理一次;主要思路是确保消息的:1)持久化;2)消息ACK后才认为已消费;
  11. 支持一个聚合根一次可以产生多个domain event;虽然大部分情况,一个聚合根一次只会产生一个domain event,但有些场景,可能会产生两个或多个。此时,这些事件会以一个事件流的方式一起apply到当前聚合根;同时,在Q端,框架也会通过必要的手段,与用户代码一起保证了事件流中的事件的处理顺序的正确性;
  12. ENode所使用的分布式消息队列EQueue,参考了阿里的RocketMQ的架构思想,具有高性能、可扩展、轻量级的特性,支持不受限于机器内存大小的消息堆积能力,而且是纯C#开发。同时还提供了简单实用的管理控制台,可以让我们轻松的管理消息队列。比如可以方便的动态增加、禁用、启用、删除队列,查询消息内容、消息消费进度,等信息;目前,EQueue也已经经过多个迭代,并且已经有真实用户进行使用,功能基本趋于成熟稳定。

Conference案例简介

Conference是一个微软开发的,基于DDD+CQRS+ES的一个开源项目。项目主页:cqrsjourney.github.io

这个项目,对我们大家学习DDD领域驱动设计、CQRS+ES的架构,非常有帮助。

  • 该案例从业务上,实现了一个典型的电子商务系统的关键环节:商品管理、库存管理、下单、减库存、支付;
  • 该案例从技术上,很好的展示了CQRS架构的优点。比如可以在Q端定制不同的视图,以应对不同的查询需求;
  • 该案例很好的向我们展示了如何划分领域,划分边界上下文(bounded context),并如何使用不同的架构技术,实现不同的上下文,非常具有学习价值。

正是因为这个项目的以上优点,让我有兴趣使用ENode作为技术支撑,实现同样功能的系统。在重写的过程中,保留了所有非技术的东西,比如边界上下文的划分、领域层等;所有技术相关的部分,用ENode替代。

使用ENode实现的Conference开源项目地址:https://github.com/tangxuehua/conference

演示地址,后台:http://www.enode.me/conference,前台:http://www.enode.me/registration

希望有兴趣的同学,可以去下载源代码进行研究。了解ENode,最快的方法就是从案例代码开始。如果想进行交流,可以加QQ群:185916873,随时欢迎有兴趣的道友加入。

最后,贴一个Conference案例中订单处理的Sagas流程图:

不早了,实在写不下去了,就到这吧。

时间: 2024-11-02 05:36:51

ENode 2.6 架构与设计简介以及全新案例分享的相关文章

应用Rational工具简化基于J2EE项目(五)架构与设计

j2ee|架构|设计|项目 第 5 部分 :架构与设计 Steven Franklin软件设计师和过程专家2004 年 4 月 当这个正在进行的应用 RUP 和其他的 Rational 工具的 J2EE 样例项目从用例转换成架构和设计时(包括数据建模和构建测试设计假想的原型),这个项目已经进入了更加技术的阶段了. 这个系列的第 5 部分首先检查了一下项目的时间进度,然后当我们进入了架构.设计.数据建模和创建原型时,我们已经在下一个阶段进行细化阶段中了. 第 5 部分快照 在第 5 部分演示的工具

演化架构与紧急设计:研究架构和设计

演化架构(evolutionary architecture)和紧急设计(emergent design)都是将 重要的决策推迟到最后责任时刻(Last Responsible Moment)的敏捷技术.在本 系列的第一期文章中,系列作者 Neal Ford 将定义架构和设计,然后指明了一些 关于整个系列的基本概念. 软件架构和设计一直都没有一个明确的定义,因为软件开发作为一门学科,尚 未完全理解其中的复杂度和内涵.但是要发表关于这些主题的论述,您必须从某 个位置开始.本系列涉及演化架构和紧急设

《架构真经:互联网技术架构的设计》大道至简

大道至简 无论从哪个角度来看,杰瑞米·金都有一个成功和绚丽的职业生涯.20世纪90年代中期,在互联网大潮来袭之前,杰瑞米参与了海湾网络公司SAP项目的成功实施.从此,杰瑞米投身互联网大潮,任Petopia.com公司的技术副总裁.他经常调侃说,在Petopia.com公司的这段经历,相当于从"硬汉拓展营大学"取得了"现实世界的工商管理硕士".离开Petopia.com后,杰瑞米加入eBay,作为总监负责新一代商务平台V3的架构.如果说杰瑞米在Petopia.com完

《架构真经:互联网技术架构的设计》水平扩展

本节书摘来自华章出版社<架构真经:互联网技术架构的设计>一书中的第1章,第3节,作者 小象学院 杨 磊,更多章节内容可以访问"华章计算机"公众号查看. 水平扩展 在实践中,我们经常告诉客户,"向上扩展注定会失败".这是因为在超高速增长的环境里,公司计划以水平方式扩展(又称之为向外扩展)至关重要.大多数情况下,这是通过对跨越多个系统工作负荷的拆分或者复制完成的.数据拆分的实施,类似我们在第2章中描述的众多方法中的一种,当超高速增长的公司无法扩展时,他们唯一

Hadoop分布式文件系统:架构和设计要点

Hadoop分布式文件系统:架构和设计要点 原文:http://hadoop.apache.org/core/docs/current/hdfs_design.html一.前提和设计目标 1.硬件错误是常态,而非异常情况,HDFS可能是有成百上千的server组成,任何一个组件都有可能一直失效,因此错误检测和快速.自动的恢复是HDFS的核心架构目标. 2.跑在HDFS上的应用与一般的应用不同,它们主要是以流式读为主,做批量处理:比之关注数据访问的低延迟问题,更关键的在于数据访问的高吞吐量. 3.

ENode 1.0 - Command Service设计思路

开源地址:https://github.com/tangxuehua/enode 上一篇文章,介绍了enode框架的物理部署思路.本文我们再简单分析一下Command Service的API设计: Command Service在enode框架中的地位非常重要,用户使用enode框架的主入口就是command service.UI层如controller会通过发送command给command service,然后框架就开始处理该command.不然看出,command service有可能会被

Android存储系统的架构与设计

一.概述 本文讲述Android存储系统的架构与设计,基于Android 6.0的源码,涉及到最为核心的便是MountService和Vold这两个模块以及之间的交互.为了缩减篇幅,只展示部分核心代码. MountService:Android Binder服务端,运行在system_server进程,用于跟Vold进行消息通信,比如MountService向Vold发送挂载SD卡的命令,或者接收到来自Vold的外设热插拔事件.MountService作为Binder服务端,那么相应的Binde

《高并发Oracle数据库系统的架构与设计》一1.3 在Oracle的世界里

1.3 在Oracle的世界里 如果你是一位Oracle数据库的使用者,那么我们说你将是立足在Oracle的世界里的.本书的主旨也是以此为出发点,立足Oracle的世界,以海纳百川的胸怀选择性吸收各种数据库的使用.立足点的不同,同样会影响到我们视角不同,那么在Oracle的世界里的高并发数据库系统架构设计将会是怎么样的呢?这也将是本书需要给读者们介绍的.相信在每一个Oracle数据库用户的眼中都有其独特的风景,对Oracle的理解可以是技术的,更可以是艺术的.在讨论中,我经常提及的一个观点:"将

Hadoop集群环境下的网络架构的设计与优化

Hadoop集群环境下的网络架构的设计与优化 冯力 杨凯 杨帆 大数据时代,研究大数据的IT厂商把研究重心放在优化大数据系统软件架构.优化业务逻辑.优化数据分析算法.优化节点性能等方向,而忽略了大数据环境基础设置中网络环节的评估和优化.本文介绍了思科公司在Hadoop集群环境下的网络架构设计与优化经验.大数据Hadoop环境网络特性Hadoop集群中的各节点通过网络连接起来,而且MapReduce中的以下过程会在网络中传输数据. Hadoop集群环境下的网络架构的设计与优化