Event Sourcing
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中消息的重复发送,这是有可能出现的。
Event Sourcing的更多相关文章
- 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 ...
- DDD CQRS和Event Sourcing的案例:足球比赛
在12月11日新的有关DDD CQRS和Event Sourcing演讲:改变心态- 以更加面向对象视角看待业务领域建模中,作者以足球比赛football Match为案例说明传统编程方法和CQRS的 ...
- 事件溯源模式(Event Sourcing Pattern)
此文翻译自msdn,侵删. 原文地址:https://msdn.microsoft.com/en-us/library/dn589792.aspx 本文介绍了一种有利于物化(materialize)领 ...
- [外文理解] DDD创始人Eric Vans:要实现DDD原始意图,必须CQRS+Event Sourcing架构。
原文:http://www.infoq.com/interviews/Technology-Influences-DDD# 要实现DDD(domain drive design 领域驱动设计)原始意 ...
- 1.2 Use Cases中 Event Sourcing官网剖析(博主推荐)
不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Event Sourcing 事件采集 Event sourcing is a st ...
随机推荐
- Hibernate4 : 持久化你的第一个类
由于目前我在学校的一个实验室跟老师学习Java EE开发,老师用的是Seam框架接活做项目,所以这一系列的文章将会向Seam方向写..路线大致应该是 : JSP --> Servlet --&g ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(一) Caching Application Block (高级)
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(一) Caching Application Block (高级) Caching Application Bl ...
- 点集配对问题(状态dp)
给定n个点(n是偶数)使得两个点两两配对,最后总的距离和最小. 用是表示集合,那么dp[s]表示集合s配对后的最小距离和 , 状态转换方程为 表示集合中任意拿两个元素配对,然后转移为更小的两个集合 ...
- 【python下使用OpenCV实现计算机视觉读书笔记4】保存摄像头视频
读取摄像头内容,然后保存一段十秒钟的视频. import cv2 cameraCapture = cv2.VideoCapture(0) fps = 30 # an assumption size = ...
- POJ1300(欧拉回路)
Door Man Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2139 Accepted: 858 Descripti ...
- 面向对象的方式进行数据交换网络之间的差异--无缝切换的发展到单机游戏C/S模式
上一页本文描述描述有关数据的发展过程之间的差异支撑点,这里展示的另一个特点:无缝切换的发展,以独立C/S模式 一般C/S模式都面临一个问题: 就是开发过程中的调试难题,由于涉及到client和服务端相 ...
- Outlook将收到邮件的附件保存在磁盘
1. 新建一个宏 1)文件->选项->自定义功能区, 把主选项卡的 开发工具勾选上. 2)开发工具->宏,输入宏名,创建. 加入以下代码 Public Sub SaveAttach( ...
- Red Gate系列之五 .NET Reflector 7.6.1.824 Edition .NET程序反编译神器(附插件安装教程2012-10-13更新) 完全破解+使用教程
原文:Red Gate系列之五 .NET Reflector 7.6.1.824 Edition .NET程序反编译神器(附插件安装教程2012-10-13更新) 完全破解+使用教程 Red Gate ...
- 即时编译和打包您的 Groovy 脚本(转)
在本文中将会涉及到: 使用 CliBuilder 来实现对命令行选项的支持,脚本执行时所需要的参数将通过命令行选项的方式传递. 使用 GroovyClassLoader 加载 Groovy class ...
- sql二进制数据权限
(3为权限组合值,结果为1=列表 2=新建 4=修改 8=删除) select 3 & 1 select 3 & 2 select 3 & 4 select 3 & 2 ...