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 ...
随机推荐
- 动态接口服务 webservice
private void GetDll() { WebClient client = new WebClient(); string url = "http://xxxx/services/ ...
- LeetCode: Valid Palindrome [125]
[题目] Given a string, determine if it is a palindrome, considering only alphanumeric characters and i ...
- spoj Balanced Numbers(数位dp)
一个数字是Balanced Numbers,当且仅当组成这个数字的数,奇数出现偶数次,偶数出现奇数次 一下子就相到了三进制状压,数组开小了,一直wa,都不报re, 使用记忆化搜索,dp[i][s] 表 ...
- Android Ant 和 Gradle 打包流程和效率对照
一.Ant 打包:(下载ant.配置环境变量就不说了) 1.进入命令行模式,并切换到项目文件夹.运行例如以下命令为ADT创建的项目加入ant build支持: android update proje ...
- 线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的使用方法
线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的使用方法 注:使用结构CRITICAL_SECTION 需增加头文件#include “afxmt. ...
- dedecms 织梦显示时间格式
field:pubdate function=GetDateMK(@me)/] 2009-11-10 [field:pubdate function=GetDateTimeMK(@me)/] 2009 ...
- Jetty安装学习并展示
Jetty 的基本架构 Jetty 眼下的是一个比較被看好的 Servlet 引擎,它的架构比較简单,也是一个可扩展性和很灵活的应用server,它有一个基本数据模型,这个数据模型就是 Handler ...
- 读懂IL
读懂IL 先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用.到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西.最重要的理 ...
- struts2在<s:select>用动态标签
后台传过来的必要性userlist成为一个下拉菜单.因此,认为使用<s:select>.但设置了很久设置的属性,在这个下跌. JSP代码: <s:select label=" ...
- 【6】和作为连续序列s
称号:输入一个整数s,并打印出所有s整数的连续序列(含有至少2的数量). 如输入9,输出2.3.4和4.5两个序列 方案一:因为序列至少要2个数,则两个数上限值为(1+s)/2,我们能够枚举该序列的起 ...