1. 程式人生 > >Axonframework框架簡介(一)

Axonframework框架簡介(一)

架構概述

https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-L9ehuf5wnTxVIo9Rle6%2F-LF1MF4RtQNtSyAx0VL4%2F-L9eiEg8i2dLcK2ovEZU%2Fdetailed-architecture-overview.png?generation=1529048013327425&alt=media

                                                    圖1

圖1為axon官方提供的基於cqrs概念和事件驅動設計的系統結構圖。

名詞解釋:

Command:命令,它包含了所有事件處理器(command handler)需要的資料。如果我們使用的是axon框架(以下關於axonframework都簡稱axon)那麼框架會給我們提供一個command bus,他會幫助指引command通向相應的command handler,命令處理器當中包含了相應的執行邏輯。

這裡的domain指的是ddd(領域驅動設計)當中的聚合,可以參考《實現領域驅動設計》(美)弗農著的這本書,裡面有很多關於領域驅動設計的概念,而axon當中的一些概念也類似於領域驅動設計中的概念。

從axon3.1開始框架開始提供query元件,這個元件能夠幫助我們類似於command和command bus一般進行查詢,一般查詢結果為只讀的dto,類似圖一可以直接對映到ui當中的特定檢視。

訊息概念

Messgae作為axon當中一個重要的概念,所有元件之間的交流都是通過message來實現的,比如event會被包裝成message然後傳送到event bus當中進行分發。

Message在axon當中作為一個interface包含以下一些方法:

不難看出message當中應該包含identifier,playload,metadata這幾個變數

Indentifier:身份標識

Playload:作為訊息的功能描述,內部會包含物件的類名,資料,描述訊息的意義。

Metadata:描述訊息上下文,不如可以加入訊息的trace information(訊息一路是怎麼傳遞的)

注意:當自己編寫message時,message應當是不可變的,如果需要加入資訊,應當是在之前的基礎上重新建立一個訊息,這樣可以保證再多執行緒環境下的安全性。

接下來會介紹訊息的型別。

Command

用POJO實現command,以官方的例子為例,如下圖(註解使用的是lombok,具體安裝方法可以百度,使用下來感覺還是很不錯的,能省略大量程式碼)

然後經過commandMessage包裝之後傳送到相應的處理器當中。如果是包含繼承關係的command和實現commandHanler類之間會有具體的情況。(如果在不同的類當中有相同的command,則呼叫其中一個,如果是aggregate中的則先呼叫aggregate中的,如果都是aggregate則看註冊的先後順序,後面註冊的會覆蓋先註冊的)

Event

區別於命令,在axon中一般command不會對實際的聚合做狀態的改變,只有在event當中才會對修改的狀態進行改變。(官方有個建議是事件最好是serializable,axon提供事件溯源的功能,而這一切真是基於對於事件的儲存,而序列化事件能夠很好的幫助儲存)

Event一般會包裝在eventMessage當中,然而如果是在aggregate當中發生的時間則會包裝在DomainEventMessage。相對於message,eventmessage多出了timestamp,domainEventMessage多出了事件流的序號,聚合的型別和標識,可以方便以後的回溯。

Query

Query從字面上就很容易理解,就是查詢相關的資訊或者狀態。

Unit of Work

Unit-of-work的目的地是協調各個messgae之間執行期間的操作,元件可以註冊各種各樣的邏輯在工作單元的各個階段,比如onPrepareCommit和onCleanUp。

一般而言不會需要處理Unit of work不過如果真的有需求的話,axon也提供了相應的方法獲取相應的unit-of-work。比如在handler的傳入引數中加入UnitOfWork引數,當然你也可以使用CurrentUnitOfWork.get()方法獲取當前執行緒繫結的unit-of-work,不過這個方法可能會丟擲相應的異常(IllegalStateException("No UnitOfWork is currently started for this thread.");程式碼摘自CurrentUnitOfWork類),所以類似於執行緒也提供了CurrentUnitOfWork.isStarted()判斷是否存在。訪問當前的unit-of-work可以附加那些可以重複使用的資源。

Unit-of-work雖然有點看起來像事務,但它並不能像事務一般如果其中一項提交失敗則全部失敗回退。所以一般建議每個command當中只包含一個操作,如果需要支援事務,可以使用官方推薦的saga這也會在後面講到。