以發(fā)布事件的方式去通知領域內的更改,可實現(xiàn)不同領域彼此分離。但是如果邏輯事件流的確存在,事情就變得不明顯了,并難以領會了。更好的解決方案是使用過程管理器(Process Manager)對全過程進行追蹤。這是Bernd Rücker在今年的DDD eXchange大會上演講中提出的,演講的內容涉及長期運行過程和領域驅動設計(DDD,Domain-Driven Design)。
Rücker在長期運行過程上具有十多年的工作經驗,他也是Camunda的聯(lián)合創(chuàng)始人。在他看來,網購的過程從用戶的角度看是十分簡單的,就是下單、支付和快遞。從DDD角度看,實現(xiàn)網購可能需要四種業(yè)務能力及相應的受限上下文,包括商店、支付、盤存和快遞。這些上下文進而生成了匹配網購過程的領域事件,即下訂單、收到付款、貨物分揀和商品快遞。
為完成下訂單過程,上下文需要協(xié)作并響應所提交事件。當一個下單事件提交后,訂閱此事件的支付上下文將在會在完成支付事件提交前,收到訂單的支付款。一個問題是,支付上下文需要知道訂單的支付時間,以及所以可觸發(fā)支付的事件。實際上,這就意味著一旦新客戶需要支付,必須要訪問支付上下文。
Rücker指出,雖然事件流導致了低耦合,但是其中并沒有過程這一概念。這是事件流的一個問題,導致整個邏輯流非常難以看到,就此問題他提及了Martin Fowler的一篇文章。另一個問題是,導致事件流發(fā)生更改的新業(yè)務需求(例如VIP客戶可以要求帶發(fā)票的訂單),可能需要更改多個上下文。
Rücker提出了一種更好的解決方案,即使用過程管理器在一個地點上跟蹤整個過程。其中過程管理器的主要職責是:
事件到命令的轉化。下單事件是已經發(fā)生的事件,隱含了我們的確希望發(fā)生的一些事情、一個命令等。在本例中,這可以是讀取支付命令。以領域邏輯一等公民實現(xiàn)事件流。事件流的整體以及每個獨立步驟中的邏輯,是所涉及的上下文中的領域邏輯的組成部分。為長期運行流處理狀態(tài)。在Bücker看來,狀態(tài)處理是實現(xiàn)中最具挑戰(zhàn)的事情。其實現(xiàn)方法包括:
Actor模型,其中actor持有本地狀態(tài),模型可使用Akka等。一個actor用于實現(xiàn)過程管理器,對整體流負責。這一方法在Vaughn Vernon所著的《Reactive Messaging Patterns with the Actor Model》一書中也做了介紹。
在實體中保持過程流的狀態(tài)。就Rücker的經驗而言,這是一種十分常見的實現(xiàn)方法。
程單模式(Routing Slip)。其中所需的所有步驟一并通過消息發(fā)生,避免了集中存儲過程狀態(tài)的需要。
定義了各個步驟的狀態(tài)機。Rücker指出,對過程狀態(tài)的可見性是使用狀態(tài)機一個優(yōu)點。
在與實現(xiàn)長期運行過程的客戶的工作經驗中,Rücker接觸到了一些常犯的錯誤,其中包括使用無工作流或是自研發(fā)的引擎,以及使用無代碼套件。為此,他推薦使用一些可嵌入到用戶代碼中的開源輕量級框架庫,Camunda是其中之一。他還建議僅去實現(xiàn)那些通用的用例,剔除一些十分異常的用例。這可能會關照到99%的用例,剩余的留給人工干預。這一做法也得到了Greg Young的推薦。
Rücker在GitHub上發(fā)布了一個例子。該例子使用在演講中給出的方法實現(xiàn)了一個基本的訂單系統(tǒng)。
明年的DDD eXchange大會計劃于2018年4月26日至27日期間在倫敦召開。
查看英文原文: Process Managers in Event-Based Systems