此模式是 "取代舊系統的模式" 的一部分

事件攔截

攔截任何系統狀態更新,並將其中一些路由到新的元件

2024 年 3 月 5 日

Ian CartwrightRob HornJames Lewis

當我們一次一部分地尋求取代舊系統時,我們會試圖找出、萃取和取代應用程式功能。為此,我們將介紹舊系統及其替換系統都需要互動的情況 - 無論是處理狀態變更、處理命令、查詢或使用者互動。舊系統通常難以或成本高昂地變更(解決此挑戰可能是進行取代計畫的主要原因),因此我們需要一種機制,讓新系統提供的功能可以整合,同時將對舊系統的影響降到最低。

透過事件攔截,我們找出舊元件之間現有的整合點,並盡可能利用它們作為可讓我們引入新功能的接縫。

運作方式

legacy systems may have numerous targets for Event Interception

舊系統可能且通常有許多事件攔截目標,包括訊息使用者、http API、SQL 連線、批次作業和其他。

我們利用舊元件之間現有的整合點,也就是上述的「技術接縫」,讓我們可以拆解、萃取或與新的應用程式元件整合。事件攔截是一種使用這些技術接縫的技術,方法是讓從一個元件傳遞到另一個元件的事件被攔截並路由到新的元件/服務。在這樣做的過程中,我們希望

  • 最小化對舊有元件的變更 - 無論是建立或使用事件的元件
  • 允許事件路由到新系統 - 有或沒有重複

訊息基礎架構

如果訊息基礎架構已經開始運作,那麼你很幸運 - 其主要優點之一是它將訊息的生產者與消費者分開。

Messaging decouples producer from consumer

Wire TapMessage RouterContent-Based Router 等模式可用於攔截和/或建立事件,這些事件可以由新系統或現有的舊有系統路由和處理以進行處理。訊息基礎架構通常允許使用訊息標頭來過濾訊息,讓某些訊息可供消費者使用。例如,JMS 實作使用訊息選擇器來允許訊息提供者過濾訊息。如此便可達成簡單的攔截和路由。

Message Routing with Message Selectors

在上述圖中,舊有消費者需要將其生產者設定為包含訊息選擇器(以有效新增篩選器)

更複雜的路由可能需要檢查訊息主體 - 在這種情況下(基於內容的路由),訊息需要由路由元件使用,檢查訊息載荷,並根據訊息內容按需要將訊息重新排入新的目的地佇列。

Content Based Message Routing

同樣地,舊有消費者需要重新設定為從新的目的地使用

反向代理 - 基於 URL、查詢參數或表單資料的路由
反向代理可以是建立和/或攔截事件的另一種非常有效的方法 - 讓您可以將 http(s) 要求重新導向到不同的資源。與訊息基礎架構類似 - 反向代理通常能夠在簡單檢查主機和埠部分、路徑、查詢參數和標頭後路由要求。

Reverse                                                                         Proxy                                                                         Routing                                                                         Requests

例如,根據表單資料內容路由要求可能需要自訂實作,但可以提供很大的彈性。

API 閘道

API 閘道在服務的公開端點和其實作之間提供一層間接。在粗略的層級上,API 閘道讓我們有機會套用 Branch by Abstraction 模式,讓閘道可以將所有要求路由到我們選擇的實作。在更精細的粒度上,也可能根據要求或載荷內容按需要路由服務要求。

在網路應用程式中 - 漸進式增強

此處的想法是對舊式網頁應用程式進行小幅變更,進而將現代化工作的發布週期與舊式應用程式的後續變更脫鉤。為此,您可以將指令碼元素新增至範本(或範圍內的每個頁面)。該指令碼可以隨著時間推移進行開發(並獨立發布),並使用漸進式增強來攔截使用者動作並視需要變更行為。例如,您可以使用此方法附加或覆寫事件處理常式,以變更表單提交到的 URL。在新增漸進式增強之前

Before using Progressive Enhancement to intercept events

以及之後

Using Progressive Enhancement to intercept events

我們曾成功使用此方法的一個範例是在網頁商店中替換舊式產品圖片解決方案。我們建置了一個新系統,使用戶能夠提交多張產品圖片,並讓專業使用者進行品質保證。我們能夠對舊式商店的全球範本進行簡單變更,以新增指令碼標籤,其 JavaScript 內容可以獨立發布。指令碼在商店中使用漸進式增強,以檢查新系統是否具有產品圖片,如果有,則為這些圖片建立輪播。顯示具有多個詳細圖片的高階輪播,可以提高售價。

資料庫層 - 觸發器

當變更已傳遞到舊式資料庫時,您可能會認為攔截事件為時已晚。話雖如此,可以使用「預提交」觸發器來攔截資料庫寫入事件並採取不同的動作。例如,可以將列插入到單獨的事件表中,以便由新元件讀取/處理 - 同時繼續進行寫入(或中止寫入)。請注意,如果您變更現有的寫入行為,應特別小心,因為您可能會破壞重要的隱含合約。

案例研究:遞增網域萃取

我們的團隊之一為客戶工作,該客戶的舊式系統有穩定性問題,且已變得難以維護且更新速度緩慢。

該組織希望解決此問題,並已決定對他們而言最合適的解決方法是使用服務導向架構實現的功能取代舊式系統。

團隊採用的策略是使用絞殺無花果模式,並一次提取一個網域,直到幾乎沒有原始應用程式為止。其他考量因素包括

  • 需要持續使用舊系統而不中斷
  • 需要持續允許舊系統的維護和增強(儘管允許將變更最小化到正在提取的網域)
  • 舊應用程式的變更應最小化 - 對於舊系統的保留知識非常不足

舊狀態

下圖顯示舊架構的架構。巨型系統的架構主要是表示層-網域-資料層

第 1 階段 - 單一網域的暗黑啟動服務

首先,團隊為單一商業網域建立一組服務,以及讓這些服務公開的資料與舊系統保持同步的功能。

這些服務使用暗黑啟動 - 也就是說,沒有任何使用者使用,相反地,這些服務讓團隊驗證資料移轉和同步是否與舊資料儲存達到 100% 的同等性。如果對帳檢查有任何問題,團隊可以推理並修復它們,確保達成一致性 - 且不會對業務造成影響。

歷史資料的移轉是透過「單次」資料移轉程序來達成。儘管不完全是事件攔截,但持續的同步是使用變更資料擷取 (CDC) 程序來達成。

第 2 階段 - 攔截所有讀取並重新導向到新服務

對於第 2 階段,團隊更新舊的持續性層,以攔截並重新導向所有讀取作業(對於此網域)以從新的網域服務擷取資料。寫入作業仍使用舊資料儲存。這是抽象分支的範例 - 持續性層的介面保持不變,並實作新的基礎實作。

第 3 階段 - 攔截所有寫入並重新導向到新服務

在第 3 階段發生許多變更。寫入作業(針對網域)會被攔截並重新導向,以在新的網域服務中建立/更新/移除資料。

此變更讓新的網域服務成為此資料的記錄系統,因為舊的資料儲存庫不再更新。任何下游使用該資料的方式,例如報表,也必須移轉為新網域服務的一部分或使用新網域服務。

第 4 階段 - 將網域業務規則/邏輯移轉到新的服務

在第 4 階段,業務邏輯移轉到新的網域服務中(將它們從貧血的「資料服務」轉換成真正的業務服務)。前端保持不變,而且現在使用舊式外觀,將實作重新導向到新的網域服務。

何時使用

如果您使用 Strangler Fig 模式,您也會使用某種形式的事件攔截。如果您有創意,您會發現有很多地方可以使用此模式建立接縫。

一些替代方法/考量

人類事件攔截器

假設事件源自使用者動作,您可能可以透過讓使用者執行其他動作來在來源攔截該事件!重新設計業務流程以充分利用現代化工作,可能表示舊式事件不再適用。如果適用,您可能可以在一段時間內權衡降低使用者體驗品質和潛在降低營運效率,而不必建立技術接縫。所謂的「旋轉椅整合」,要求使用者在新系統和/或舊系統上執行特定動作,可能會提供您快速取代舊式部分所需的接縫。

資料庫觸發器 - 後提交

「提交後」觸發器不會攔截寫入事件,但也可以用於建立事件,以通知其他系統已發生特定狀態變更。

變更資料擷取 (CDC)

CDC 包含允許您從附加到資料庫交易記錄的項目建立事件串流的技術。例如,我們的團隊使用 Debezium 建立 Kafka 事件串流的經驗良好,新應用程式可以使用該串流。同樣地,事件串流可以由並行運作的新系統使用,這並非嚴格意義上的攔截。

在舊系統中路由事件

事件攔截的其中一個目標是將更新舊系統的需求減到最低或避免更新舊系統,以與新系統整合,但一個顯而易見的替代方案是在可能的情況下修改呼叫者,讓呼叫者直接呼叫新系統,而不是引入攔截器。一些需要考慮的權衡

  • 區分問題和必要的複雜性。
    呼叫者需要承擔所有功能,以及攔截器原本會承擔的可操作性疑慮。例如,了解新系統介面的合約、訊息結構、錯誤處理、記錄、監控和警示等。
  • 避免額外的複雜性。
    修改舊系統可以避免需要在組合中新增另一段過渡架構。這表示出錯的機率較低、操作次數較少,以及認知負擔降低。
  • 如果整合有多個呼叫者呼叫單一介面,且該介面的提供者正在被取代,則值得考慮改用舊系統模擬模式。新元件將實作舊系統介面,並因此承擔事件攔截器的責任,而不會新增額外的過渡架構

進一步閱讀

此模式和舊系統模擬是說明如何實現 Martin 最初文章中更廣泛的絞殺無花果模式的範例。

此模式最初於 2004 年由 Martin Fowler 在此網站上以 bliki 條目發布,此文字取代了該說明。

重大修訂

2024 年 3 月 5 日