Event Sourcing - ENode(二)
接上篇文章继续
http://www.cnblogs.com/dopeter/p/4899721.html
分布式系统
前篇谈到了我们为何要使用分布式系统,因为ENode本身就是一个分布式的框架。看了很多DDD、CQRS的框架,一般情况是一个上下文一个系统,可以多分系统实例进行分布式部署,但需要自己搭配分布式的基础设施。而ENode已经提供了较为完整的分布式DDD解决方案。
1. 分布式通讯基础设施
一般使用RPC、MOM、REST,不过最近REST已经逐渐弱化特别是在一个大系统的内部,或者是对性能要求较高的场景,作者自己实现并开源了MOM组件EQueue作为基础设施搭配ENode,有一些Kfaka的设计理念,但加入了自己的设想,可以到作者的博客上了解了解。
http://www.cnblogs.com/netfocus/category/496012.html
2. 分布式的粒度
这是ENode最大的亮点,从目前业内的发展的大方向来说,也是ENode能被投入生产环境试运行的原因之一。ENode是以Command、Event、Application Message、Exception为基础粒度采用的分布式设计。目前其他的CQRS框架大多都还是系统实例级的分布式,如果要实现这种粒度的分布式,需要自己动手设计,从长远来看,如果真的投入到生产环境,框架升级之后引发的不兼容等问题是很有可能的,当然ENode如果能成为我们目前OLTP系统的流行框架的话,还是得小心以后被作者绑架。
关系数据库
作者在框架中其实一直在使用关系数据库,因为有了前面粒度的铺垫,再加上ES本身的写屏障特性,实现了类似关系数据库的一致性,而只使用了关系数据库的持久化以及检查机制。当然作者在实现中仍然使用了事务,以及将关系数据库当分布式的锁来使用,有点类似ZooKeeper,这些都是基于的是粒度的缩小,所以性能上是有很大的提高。不过这些是作者的默认实现,我们可以自己实现另外一套。
其实应该从Sample开始讲的,不过如果有兴趣的朋友可以直接去下载作者的源码,作者的Sample写的很好,所以直接开剖。
全观
这是ENode的代码。
我们可以认为分为2层,开发者应用层(业务开发人员专用),基础设施层(架构开发人员专用) 。
Commanding,Domain,Eventing,Snapshoting属于应用层。是ES的专用术语。
Infrastructure和Configurations则是基础设施层。
Commanding
我们可以认为这是Commanding的装配图,顾名思义。
ICommand,一个命令
继承了IMessage,这就是前面提到的分布式消息。
其他的接口都是顾名思义。
ICommandHandler 命令处理者
ICommandHandlerProvider 隔离命令处理者的装配
ICommandHandlerProxy 命令处理者代理
Async则是代表异步的
就不一一介绍了。重点是看作者实现的默认的组件。
面向接口是代表作者抽象的高度与角度,真正代表其落地思想的则是其默认实现的类。
内容有点多,而且会很跳跃,这篇是讲不完的,我们还是慢慢来。主要是打字打的有点累了,手跟不上脑。先看看作者实现的DefaultProcessingCommandHandler类,
这是较为核心的,也可以认为是核心处理Command逻辑的类。
它实现了IProcessingMessageHandler接口,这个接口只有一个方法
void HandleAsync(X processingMessage);
于是我们就顺藤摸瓜看看作者的实现。
屏幕太小,截了2张图,第一张没什么特别的,第二张,这里使用了2个不同的Handler,一个是同步的,一个是异步的。它们的逻辑会有一些不同。
当然肯定是会执行Command的处理方法的。区别是什么呢?
在HandleCommand方法中,执行完后,有一些判断Command是否只是修改单个聚合根的逻辑,这里体现的是作者设计思想中的单个聚合根隔离性,也就是前篇所讲的关系数据库中事务隔离性粒度放至聚合根的粒度。在经过验证后,会直接提交Event,准备持久化Event,执行后续的,Event后续再讲。
在ProcessCommand方法中,用到了CommandStore,在作者默认实现的CommandStore中有2种实现方式,InMemory以及SQLSERVER,InMemory中是将Command存储在字典中,SQLSERVER则是以Command的ID作为主键,这里的逻辑是首先去CommandStore中检索是否存在相同ID的Command,如果有,则被证明是执行过了。如果没有,则继续执行Command,Command执行成功后,将Command保存至CommandStore中,保存成功后提交Event,准备持久化Event。这里实际上是在消除Command的幂等,第一个乐观锁机关出现了。
为什么第一个方法不使用乐观锁,而直接发布事件呢。
HandleCommand方法中的Command所对应的聚合根实际上还没有被更新,只是预提交一个Dirty的聚合根数据至EventHandler处,在EventHandler处会再次有乐观锁机关。
为什么ProcessCommand方法中要使用乐观锁呢,其实我没有完全的答案,猜测有以下几点
1. 见上图的If ,else if处,对一个Command来说,是可以有多个Handler的,无论是在系统实例内部或是其他并行的系统实例,再或者是其他上下文的系统实例,都有可能会有同步以及异步处理的Handler。
2. ProcessCommand方法是对应的异步CommandHandler,既然是异步的,作者使用了.NET的Task,虽然一个Command是单线程在跑,不过要是在异步中,例如我们和另外的系统通讯也使用了异步,那么这个线程就会返回,执行下一个Command,如果下一个Command相同,这个理论上是不大可能的。
3. MOM中消息的重复发送,这是有可能出现的。
关于上面猜测,作者的官方解释
所以不需要异步处理
而不操作聚合根时基本是调用其他外部IO接口,所以需要异步
另外,不操作聚合根的命令也一定会有一个关联的聚合根ID,这是框架的要求
比如转账前要求验证账号是否合法,可能是调用外部接口,但我们一定知道是要验证哪个聚合根的
虽然框架里目前没使用这个聚合根ID,但至少cmdstore会记录下来
方便我们跟踪命令和聚合根的可能对应关系
一个cmd归纳起来可以理解为有两种目的,1:操作某个聚合根,2:验证和某个聚合根相关的某种外部逻辑或规则
Event Sourcing - ENode(二)的更多相关文章
- Event Sourcing - ENode(一)
分布式系统 摩尔定律如果一直能实现,不管是涉及或者实现一个OLTP的系统,我们是不是都会轻松点,用硬件堆就可以了.但是现在硬件已经在求变了,那么我们也得求变,云的概念如此之火,本质就是设施虚拟化,也可 ...
- Event Sourcing - ENode(三)
接上一篇 http://www.cnblogs.com/dopeter/p/4903328.html 老板昨天在第二篇介绍中回复代码和文字无法一一对应.为了更好的让老板为大家解惑,把第二篇最后的猜测的 ...
- Event Sourcing
Event Sourcing - ENode(二) 接上篇文章继续 http://www.cnblogs.com/dopeter/p/4899721.html 分布式系统 前篇谈到了我们为何要使用分布 ...
- CQRS与Event Sourcing之浅见
引言 DDD是近年软件设计的热门.CQRS与Event Sourcing作为实施DDD的一种选择,也逐步进入人们的视野.围绕这两个主题,软件开发的大咖[Martin Fowler].[Greg You ...
- Event Sourcing Pattern 事件源模式
Use an append-only store to record the full series of events that describe actions taken on data in ...
- CQRS, Task Based UIs, Event Sourcing agh!
原文地址:CQRS, Task Based UIs, Event Sourcing agh! Many people have been getting confused over what CQRS ...
- Typed Message模式与Event Sourcing
引言 在<设计模式沉思录>(Pattern Hatching: Design Patterns Applied,[美]JohnVlissides著)一书的第4章中,围绕事件Message传 ...
- DDD创始人Eric Vans:要实现DDD原始意图,必须CQRS+Event Sourcing架构
http://www.infoq.com/interviews/Technology-Influences-DDD# 要实现DDD(domain drive design 领域驱动设计)原始意图,必 ...
- Event Sourcing pattern
Event Sourcing pattern Instead of storing just the current state of the data in a domain, use an app ...
随机推荐
- 两个实验操作系统-ubuntu在安装配置pintos
安前两次莫名其妙, 蛋疼的实验操作系统.. 首先下错了总结第一次. 使用最后gdb调试pintos什么时候, 这个错误将被报告: bochsrc.txt:8: Bochs is not compile ...
- ostringstream使用
ostringstream使用 [本文来源于]http://www.builder.com.cn/2003/0304/83250.shtml http://www.cppblog.com/alanto ...
- KMP算法---字符串匹配
算法细节详见点击打开链接和点击打开链接 #include <stdio.h> #include <stdlib.h> #define N 7 #define M 15 void ...
- Holding Bin-Laden Captive!(杭电1085)(母函数)
Holding Bin-Laden Captive! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...
- C#四舍五入保留两位小数
- HDU ACM 4578 Transformation->段树-间隔的变化
分析:复杂的经营分部树. 只有一个查询操作,这是要求[l,r]的数量之间p钍总和.并不是所有的查询所有节点,会议TLE.最好的是查询部件[a.b].所有这个区间值我们是平等的,即能返回(b-a+1)* ...
- MessageBox()功能
MessageBox()功能.这是一个非常频繁使用的Win32 API,在屏幕上显示一个窗体,提出问题,并等待用户输入.它的原型是 int MessageBox(HWND hwnd,LPCTSTR l ...
- 成都传智职工high翻竞赛场
日前,由石羊街道总工会.天府新谷园区党委联合主办的“2013年职工趣味竞赛”盛大开幕.传智播客成都java培训中心员工积极参与,活跃在各大项目的比赛中,员工们用笑脸.身影告诉大家:竞赛场上,我们hig ...
- Gradle学习系列之一——Gradle快速入门(转)
这是一个关于Gradle的学习系列,其中包含以下文章: Gradle快速入门 创建Task的多种方法 读懂Gradle语法 增量式构建 自定义Property 使用java Plugin 依赖管理 构 ...
- POJ2239 Selecting Courses【二部图最大匹配】
主题链接: http://poj.org/problem?id=2239 题目大意: 学校总共同拥有N门课程,而且学校规定每天上12节可,一周上7天. 给你每门课每周上的次数,和哪一天哪一节 课上的. ...