AxonFramework命令總線

命令總線是將命令分發(fā)給各自的命令Handler的機制。每個命令總是被精確發(fā)送到一個命令Handler台囱。如果沒有可用的命令Handler為已分發(fā)的命令淡溯,將會拋出NoHandlerForCommandException異常。對同一命令類型訂閱多個命令Handler將導(dǎo)致訂閱互相取代簿训。在這種情況下咱娶,最后一個訂閱獲勝。

分發(fā)命令

CommandBus提供了兩個方法去分發(fā)命令到它們各自的Handler:dispatch(commandMessage,callback)和dispatch(commandMessage)强品。第一個參數(shù)是一個包含要發(fā)送的實際命令的消息膘侮。第二個可選的參數(shù)接收一個回調(diào),允許在命令處理完成時通知分發(fā)組件的榛。這個回調(diào)有兩個方法:onSuccess()和onFailure()琼了,分別會在命令處理返回后被調(diào)用,或者當(dāng)它拋出一個異常時調(diào)用夫晌。

調(diào)用組件可能不采取在分發(fā)命令的同一線程中調(diào)用回調(diào)雕薪。如果調(diào)用線程在繼續(xù)之前依賴于結(jié)果,你可以使用FutureCallback晓淀。這是一個Future(在java.concurrent包中定義)和Axon的CommandCallback的組合所袁。或者凶掰,考慮使用命令網(wǎng)關(guān)燥爷。

如果一個應(yīng)用程序不直接對命令的結(jié)果感興趣,可以使用dispatch(commandMessage) 方法锄俄。

SimpleCommandBus

SimpleCommandBus,顧名思義勺拣,最簡單的實現(xiàn)奶赠。它在分發(fā)它們的線程中簡單的處理命令。命令處理后药有,修改后的聚合在同一線程被保存和發(fā)布生成的事件毅戈。在大多數(shù)情況下苹丸,如web應(yīng)用程序,該實現(xiàn)將符合你的需求苇经。配置API中SimpleCommandBus是默認(rèn)使用的實現(xiàn)赘理。

像大多數(shù)CommandBus實現(xiàn)一樣,SimpleCommandBus允許攔截器進(jìn)行配置扇单。在命令總線上分發(fā)一個命令后調(diào)用CommandDispatchInterceptors商模。在實際的命令handler 方法之前調(diào)用CommandHandlerInterceptors蜘澜,允許你修改或阻塞命令。有關(guān)更多信息鄙信,請參考命令處理器攔截器。

因為所有命令處理都在同一線程中完成装诡,這個實現(xiàn)僅限于JVM的邊界。這個實現(xiàn)的性能是很好的鸦采,但不超凡∈衿幔跨JVM邊界咱旱,或使你的CPU cycles發(fā)揮最大的功效,看看其他CommandBus實現(xiàn)吐限。

AsynchronousCommandBus

顧名思義,AsynchronousCommandBus實現(xiàn)從分發(fā)它們的線程異步執(zhí)行命令诸典。它使用一個Executor在不同的線程來執(zhí)行實際的處理邏輯。

默認(rèn)情況下狐粱,AsynchronousCommandBus使用一個unbounded緩存的線程池。這意味著分發(fā)一個命令時會創(chuàng)建線程肌蜻。完成處理命令的線程將被重新用于新命令。如果60秒線程沒有處理命令蒋搜,則會停止線程判莉。

或者带迟,Executor實例可以提供不同的線程策略配置项郊。

注意锰镀,應(yīng)用程序停止時應(yīng)該關(guān)閉AsynchronousCommandBus宿刮,以確保任何等待線程正確關(guān)閉。關(guān)閉胡桃,調(diào)用shutdown()方法磕潮。這也將關(guān)閉任何Executor實例,如果它實現(xiàn)ExecutorService接口的話自脯。

DisruptorCommandBus

SimpleCommandBus具有合理的性能特性之景,特別是當(dāng)你經(jīng)歷了性能調(diào)優(yōu)技巧膏潮。事實上,SimpleCommandBus需要鎖來防止多個線程并發(fā)訪問同一聚合焕参,導(dǎo)致處理開銷和鎖爭用。

DisruptorCommandBus采用不同的方法進(jìn)行多線程處理叠纷。不是多個線程每個都執(zhí)行同樣的處理,而是有多個線程涩嚣,每個負(fù)責(zé)一件處理。DisruptorCommandBus使用Disruptor航厚,一個小的并發(fā)編程框架,通過不同的方法對多線程進(jìn)行處理來實現(xiàn)更好的性能幔睬。任務(wù)不是在調(diào)用線程中進(jìn)行處理,而是將任務(wù)移交給兩組線程進(jìn)行處理溪窒,每組線程負(fù)責(zé)一部分處理。第一組的線程將執(zhí)行命令handler澈蚌,更改一個聚合的狀態(tài)。第二組將存儲并將事件發(fā)布到事件存儲浮禾。

雖然DisruptorCommandBus輕易優(yōu)于SimpleCommandBus 4倍(!),但有一些限制:

  • DisruptorCommandBus僅支持事件溯源聚合盈电。這個命令總線充當(dāng)由Disruptor處理聚合的存儲庫。獲取一個存儲庫的引用匆帚,使用createRepository(AggregateFactory)。
  • 一個命令只能導(dǎo)致一個聚合實例狀態(tài)變化吸重。
  • 當(dāng)使用緩存時,它只允許給定的標(biāo)識符為單個聚合嚎幸。這意味著它是不可能有兩個具有相同的標(biāo)識符的不同類型的聚合。
    命令一般不會引發(fā)需要回滾工作單元的故障嫉晶。當(dāng)發(fā)生回滾時,DisruptorCommandBus不能保證命令按照它們被分發(fā)的順序進(jìn)行處理田篇。此外,它需要重試其他命令斯辰,從而造成不必要的計算。
  • 在創(chuàng)建一個新的聚合實例時彬呻,命令更新所創(chuàng)建實例可能并不完全按照所提供的順序進(jìn)行。一旦創(chuàng)建了聚合闸氮,所有命令將按照它們被分發(fā)順序執(zhí)行。為了確保順序蒲跨,在創(chuàng)建命令上使用回調(diào)去等待正在創(chuàng)建的聚合。它不應(yīng)該耗時超過幾毫秒或悲。

構(gòu)建一個DisruptorCommandBus實例堪唐,你需要一個EventStore。該組件在Repositories and Event Stores中有解釋淮菠。
或者,你可以提供一個DisruptorConfiguration實例合陵,它允許你調(diào)整配置優(yōu)化你的特定環(huán)境下的性能:

  • Buffer size:在ringBuffer上注冊傳入命令的槽數(shù)。更高的值可能會增加吞吐量,但也導(dǎo)致更高的延遲拥知。必須是2的次方數(shù)碎赢,默認(rèn)為4096。
  • ProducerType: 表示條目是由單線程或多線程生成的肮塞。默認(rèn)為多線程户侥。
  • WaitStrategy:當(dāng)處理器線程(三個線程負(fù)責(zé)的實際處理)需要等待對方時使用的策略蕊唐。最好的WaitStrategy取決于機器上可用的處理器數(shù)量,和正在運行的其他進(jìn)程的數(shù)量替梨。如果低延遲是至關(guān)重要的,DisruptorCommandBus可以自己認(rèn)領(lǐng)內(nèi)核副瀑,你可以使用BusySpinWaitStrategy。為了使命令總線索取更少的CPU并且允許其他線程處理糠睡,使用YieldingWaitStrategy疚颊。最后,你可以使用SleepingWaitStrategy和BlockingWaitStrategy允許其他進(jìn)程共享CPU均抽。如果命令總線不需要進(jìn)行專職處理,則后者是合適的油挥。默認(rèn)為BlockingWaitStrategy。
  • Executor:設(shè)置Executor為DisruptorCommandBus提供線程攘乒。這個Executor必須能夠提供至少4個線程惋鹅。其中的3個線程负饲,由DisruptorCommandBus的處理組件認(rèn)領(lǐng)返十。額外的線程用于調(diào)用回調(diào)函數(shù)椭微,并計劃重試以防檢測到錯誤的聚合狀態(tài)蝇率。默認(rèn)是CachedThreadPool提供線程從一個稱為“DisruptorCommandBus”的線程組中排拷。
  • TransactionManager:定義了事務(wù)管理器监氢,應(yīng)該確保存儲和事件發(fā)布以事務(wù)的方式執(zhí)行浪腐。
  • InvokerInterceptors:定義了在調(diào)用處理中使用的CommandHandlerInterceptors议街。這個處理調(diào)用實際的命令處理器方法璧榄。
  • PublisherInterceptors:定義了在發(fā)布處理中使用的CommandHandlerInterceptors骨杂。這個發(fā)布處理存儲和發(fā)布生成的事件腊脱。
  • RollbackConfiguration:定義工作單元應(yīng)該回滾的異常。默認(rèn)配置為回滾未經(jīng)檢查的異常悍抑。
  • RescheduleCommandsOnCorruptState:指示已經(jīng)執(zhí)行過命令但損壞的聚合(如:因為一個工作單元是回滾)是否應(yīng)該重新計劃拂盯。如果為假记靡,回調(diào)的onFailure()方法將被調(diào)用摸吠。如果為的(默認(rèn)),命令將被重新計劃寸痢。
  • CoolingDownPeriod:設(shè)置等待的秒數(shù),以確保所有命令被處理道逗。在冷卻期間滓窍,不接受新命令巩那,但是現(xiàn)有的命令仍然處理锦亦,并在必要時重新計劃令境。冷卻期間確保線程可供重新安排命令和調(diào)用回調(diào)之用舔庶。默認(rèn)為1000(1秒)。
    緩存:設(shè)置緩存存儲從Event Store中恢復(fù)的聚合實例瞧甩。緩存用disruptor存儲不活躍的聚合實例肚逸。
  • InvokerThreadCount:給命令處理器的調(diào)用分配線程的數(shù)量。一個好的起始點是機器內(nèi)核數(shù)量的一半膝晾。
  • PublisherThreadCount:用于發(fā)布事件的線程數(shù)量务冕。一個好的起始點是一半的內(nèi)核數(shù)量,如果IO上花費大量的時間臊旭,可以增加。
  • SerializerThreadCount:使用pre-serialize事件的線程數(shù)量箩退。默認(rèn)為1,但如果沒有配置序列化器將被忽略乏德。
  • Serializer:用于執(zhí)行pre-serialization的序列化器喊括。當(dāng)配置序列化器時,DisruptorCommandBus將包裝所有生成的事件在一個SerializationAware消息上郑什。附加有效負(fù)載和元數(shù)據(jù)的序列化形式蒲肋,在發(fā)布到事件存儲之前。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末申窘,一起剝皮案震驚了整個濱河市孔轴,隨后出現(xiàn)的幾起案子路鹰,更是在濱河造成了極大的恐慌,老刑警劉巖优构,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雁竞,死亡現(xiàn)場離奇詭異,居然都是意外死亡玉凯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門捎拯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盲厌,“玉大人署照,你說我怎么就攤上這事吗浩。” “怎么了懂扼?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長赶熟。 經(jīng)常有香客問我,道長陷嘴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任邑退,我火速辦了婚禮劳澄,結(jié)果婚禮上地技,老公的妹妹穿的比我還像新娘秒拔。我一直安慰自己,他們只是感情好食磕,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布彬伦。 她就那樣靜靜地躺著单绑,像睡著了一般搂橙。 火紅的嫁衣襯著肌膚如雪苔巨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音闺魏,去河邊找鬼舷胜。 笑死活翩,一個胖子當(dāng)著我的面吹牛材泄,可吹牛的內(nèi)容都是我干的吨岭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼旦事,長吁一口氣:“原來是場噩夢啊……” “哼急灭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起葬馋,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肾扰,失蹤者是張志新(化名)和其女友劉穎蛋逾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體偷拔,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡沉颂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了铸屉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡顷啼,死狀恐怖昌屉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤扛施,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布荒揣,位于F島的核電站非凌,受9級特大地震影響航背,放射性物質(zhì)發(fā)生泄漏勺像。R本人自食惡果不足惜殃姓,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一薄湿、第九天 我趴在偏房一處隱蔽的房頂上張望桥嗤。 院中可真熱鬧,春花似錦儡湾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽根时。三九已至含友,卻和暖如春窘问,著一層夾襖步出監(jiān)牢的瞬間把鉴,已是汗流浹背庭砍。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工凯旭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厌杜。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓匙握,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛾娶。 傳聞我的和親對象是個殘疾皇子峻呛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理惨远,服務(wù)發(fā)現(xiàn),斷路器蔑水,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,139評論 25 707
  • 我生產(chǎn)的經(jīng)歷不是太順利逻淌,到了預(yù)產(chǎn)期一直沒動靜骨望,醫(yī)生說超過一周就得去住院催產(chǎn)了。 盼啊盼啊,好不容易見了紅,凌晨打車...
    IceLi87閱讀 827評論 0 1
  • 白淺太過思念夜華夭坪,白真便帶著她到凡間去游歷亡鼠,這青丘狐貍洞里又只剩下鳳九與迷谷二人榜揖。所以也只有迷谷知道鳳九這幾年是怎...
    一葉明月閱讀 2,307評論 1 32
  • 前言綜述 項目中人員或組織的組織結(jié)構(gòu)對日后的項目影響深遠(yuǎn)潜叛,簡而言之有三種類型:項目型庐椒、職能型特纤、矩陣型權(quán)利: 項目型...
    jeffleefree閱讀 768評論 0 1