Conference架構概述
先貼一下Conference案例的在線地址,UI因為完全拿了微軟的實現,所以都是英文的,以后我有空再改為中文的。
- Conference后台會議管理:http://www.enode.me/conference
- Conference前台預定座位:http://www.enode.me/registration
- ENode論壇開源案例:http://www.enode.me/post
- ENode開源項目地址:https://github.com/tangxuehua/enode
前一篇文章介紹了Conference案例的上下文划分和領域模型的設計思路,本文想介紹一下Conference案例的架構設計。我做Conference案例的出發點是為了給大家展示如何使用ENode框架來開發DDD+CQRS+ES+EDA風格的應用程序。所以,Conference案例的架構自然就是使用這個架構了。下面我展開來說一下:
- DDD:是軟件設計的一種方式,出發點是通過領域模型封裝業務邏輯和業務規則,解決領域內的復雜業務問題;
- CQRS+ES:命令查詢分離的架構,通過將命令查詢分離,做到處理業務邏輯的部分和查詢的部分可以分離,方便兩部分可以各自發展,不受對方約束;CQRS的實現方式主要有兩種:1)共享存儲的CQRS,即背后的數據庫存儲是一份,數據是一份,只是在代碼、架構層面做到命令和查詢邏輯的分離。這種方式很好的利用了CQRS的思想,同時也不會有數據一致性的問題,因為是共享存儲的,所以CQ兩端不需要有消息通信,大部分應用程序用這種方式即可。2)存儲分離的CQRS,這種方式主要用ES(Event Sourcing,事件溯源)技術來徹底實現CQ兩端的完全分離,這種架構比較復雜。C端不存儲對象的最新狀態,而是存儲對象產生的所有事件;讓我們要還原一個對象時,通過ES的方式來還原。然后Q端通過訂閱C端產生的事件來更新讀庫。這種架構是一種EDA的架構,CQ兩端需要通過事件來進行聯系,所以是一種面向最終一致性思路的架構。那這種方式有何好處呢?它和前面我說的第一種方式的CQRS架構,我覺得主要的好處是,我們可以設計一套框架,幫我們從架構層面解決並發問題、消息的冪等處理問題;同時結合in-memory, group commit等技術,還能大大提高系統的吞吐量以及抵御高峰的能力(因為消息可以堆積);從而可以讓開發人員不用關心技術問題,專心實現業務邏輯和設計業務流程即可。而共享存儲的CQRS架構,是需要我們每次Command修改完聚合根之后,需要主動保存(可能通過ORM實現)聚合根的狀態的。總之兩種實現方式各有優缺點,關於CQRS架構的更多介紹,我博客里已經寫過很多文章了,有興趣的朋友可以進一步看看。
- EDA:這是一種事件驅動的架構,他和SOA架構屬於同一個層次;EDA是事件驅動的思想,即B訂閱A產生的消息來進行主動響應的思路;而SOA是一種面向服務然后通過服務之間相互調用(RPC)的思想;這是兩種不同的架構風格,我們在不同的場景會使用不同的方式。ENode實現的是EDA架構,面向的是最終一致性。ENode在很多方面都體現出了EDA的思想。比如:
- ENode規定,一個Command不能同時修改兩個聚合根,必須通過事件驅動的方式,先修改一個聚合根,然后該聚合根產生事件,然后另一個聚合根訂閱響應事件,再修改自己的狀態,從而實現兩個聚合根之間的交互。這個思路 背后的原則是:聚合內強一致性、聚合之間最終一致性。
- CQRS兩端,也是最終一致性,通過事件來同步數據。C端產生的事件通過MQ被Q端訂閱,然后Q端更新自己的讀庫,從而實現數據的最終一致性;
- 兩個BC(Bounded Context,上下文)之間的數據傳遞,也是基於消息驅動的思想。比如支付上下文在完成支付后,會產生一個消息,然后訂單上下文訂閱響應該消息,實現上下文之間的交互。
ENode架構圖
也許有人沒看過ENode架構圖,呵呵。我這里再貼一下,誰如果要進一步了解ENode的架構設計,可以看我博客中的其他關於ENode框架的介紹文章。
Conference項目結構介紹
|
前篇文章中我們了解到,Conference案例共有三個上下文,分別是:會議管理(ConferenceManagement)、訂單處理(Registration)、訂單支付(Payment)。關於這個案例,微軟的實現和我的實現有所不同,但上下文的划分是一致的。微軟的實現中,三個上下文用的技術架構是不同的。
上面我簡要分析了一下微軟的實現。我覺得微軟的實現還是非常有參考價值的,因為它充分展示了DDD中不同的BC可以采用不同的技術架構實現,然后通過EDA的整體架構,來實現3個BC之間的數據交互。非常棒。 下面我說一下ENode實現的Conference案例。 前面說過,本案例主要是為了展示ENode框架的使用,所以我給這3個BC都是使用ENode框架實現,所以每個BC都是采用的DDD+CQRS+ES的技術架構。由於有ENode框架的支持,所以代碼實現還不算復雜,可以讓開發只需要專注於業務邏輯的實現即可,不需要關心消息傳遞,消息不丟失,消息冪等處理,並發問題,C端數據持久化等技術問題。這些技術問題如果沒有框架支持,要由應用開發人員自己實現,是很有難度的。通過這個案例實踐下來,基本可以證明ENode框架是可以被使用來開發出一個可實際使用的項目的,這點我目前很有信心。 采用ENode框架開發一個BC的實現的時候,我們一般需要定義以下的一些工程:
另外,上面介紹了單個BC內部可能出現的項目,這些項目是我通過做這個案例后總結出來的覺得可以給開發者做參考的相互划分方式。大家如果覺得這樣的方式不好,可以自己決定如何划分。通過上面的划分,我們的頂層Web項目只需要依賴簡單的Commands,ReadModel這兩個項目,就可以實現命令的發送和讀庫數據的查詢了。而BC之間的交互,另一個BC只需要依賴當前BC的Messages項目就行,做到了最小的依賴。 最后介紹一下剩余的幾個頂層項目: Conference案例有兩個Web項目,分別為用戶提供Conference的后台管理和前台訂單預定的Web界面。這個不需要多解釋了應該。然后,還有3個ProcessorHost項目。這3個項目分別是3個BC負責處理后台業務邏輯的頂層宿主項目。它們只需要用控制台應用或者Windows服務的方式啟動即可(案例里的實現同時支持這兩種方式的啟動,會自動識別當前的應用程序類型)。這3個后台服務,它們都是從EQueue訂閱消息,然后處理消息的方式,實現自己的功能。所以它們的唯一數據來源就是EQueue。那EQueue消息隊列的服務端是哪個呢?就是最下面的MessageBroker,這個項目承載了整個系統的消息中心,也就是EQueue的Broker。所有的消息都會發送給MessageBroker,然后相關的ProcessorHost訂閱相關的Topic,實現消息的消費。 |
結尾
下一篇文章打算從代碼的角度,以創建一個會議為例,從前台Controller到最后更新讀庫的整個代碼鏈路簡單介紹一下,方便讀者能對實現某個功能要寫哪些代碼先有一個清晰總體的認識。