接上篇文章繼續html
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.htmlide
2. 分佈式的粒度性能
這是ENode最大的亮點,從目前業內的發展的大方向來講,也是ENode能被投入生產環境試運行的緣由之一。ENode是以Command、Event、Application Message、Exception爲基礎粒度採用的分佈式設計。目前其餘的CQRS框架大多都仍是系統實例級的分佈式,若是要實現這種粒度的分佈式,須要本身動手設計,從長遠來看,若是真的投入到生產環境,框架升級以後引起的不兼容等問題是頗有可能的,固然ENode若是能成爲咱們目前OLTP系統的流行框架的話,仍是得當心之後被做者綁架。spa
關係數據庫線程
做者在框架中其實一直在使用關係數據庫,由於有了前面粒度的鋪墊,再加上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中消息的重複發送,這是有可能出現的。
關於上面猜想,做者的官方解釋