本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 CQRS 和事件來源將巨石分解為微服務
由小魯道夫創作 賽拉達 (AWS)、德米特里古林 (AWS) 和塔比沃德 (AWS)
環境:PoC 或試驗 | 來源:巨石 CRUD 模式 | 目標:微服務 |
R 型態:重建 | 工作負載:開放原始碼 | 技能:現代化;訊息與通訊;無伺服器 |
AWS 服務:Amazon DynamoDB DynamoAWS Lambda Amazon SNS |
Summary
這種模式結合了兩種模式,使用命令查詢責任分離 (CQRS) 模式和事件來源模式。CQRS 模式分離命令和查詢模型的責任。事件來源模式會利用非同步事件導向的通訊來改善整體使用者體驗。
您可以使用 CQRS 和 Amazon Web Services (AWS) 服務獨立維護和擴展每個資料模型,同時將整體應用程式重構為微服務架構。然後,您可以使用事件來源模式,將命令資料庫中的資料同步至查詢資料庫。
此模式使用範例程式碼,其中包含您可以使用最新版 Visual Studio 開啟的解決方案 (*.sln) 檔案。此範例包含獎勵 API 程式碼,以展示 CQRS 和事件來源如何在 AWS 無伺服器和傳統或現場部署應用程式中運作。
要進一步了解 CQRS 和事件來源,請參閱其他資訊區段。
先決條件和限制
先決條件
作用中的 AWS 帳戶
Amazon CloudWatch
Amazon DynamoDB 資料表
Amazon DynamoDB Streams
AWS Identity and Access Management (IAM) 存取金鑰和秘密金鑰;如需詳細資訊,請參閱相關資源區段
AWS Lambda
熟悉 Visual Studio
熟悉適用 AWS Toolkit for Visual Studio;如需詳細資訊,請參閱AWS Toolkit for Visual Studio 示範影片相關資源區段
產品版本
.NET Core 3.1。這個元件是在 Visual Studio 安裝中的一個選項。若要在安裝期間包含 .NET 核心,請選取NET 核心跨平台開發。
限制
傳統的內部部署應用程式 (ASP.NET 核心 Web API 和資料存取物件) 的範例程式碼不會隨附資料庫。但是,它帶有
CustomerData
內存中對象,它充當模擬數據庫。提供的代碼足以讓您測試模式。
Architecture
來源碼技術堆疊
ASP.NET Core API 專案
IIS Web 伺服器
資料存取物件
CRUD 模型
來源架構
在源體系結構中,CRUD 模型在一個應用程序中包含命令和查詢接口。如需範例程式碼,請參閱CustomerDAO.cs
(已附上)。

目標技術堆疊
Amazon DynamoDB
Amazon DynamoDB Streams
AWS Lambda
(選用) Amazon API Gateway
(選用) Amazon Simple Notification Service (Amazon SNS)
目標架構
在目標架構中,命令和查詢介面是分開的。下圖所示的架構可以使用 API Gateway 和 Amazon SNS 進行擴充。如需詳細資訊,請參閲 。其他資訊區段。

命令 Lambda 函式會執行寫入作業,例如,建立、更新或刪除。
查詢 Lambda 函數在資料庫上執行讀取作業,例如取得或選取。
此 Lambda 函數會處理命令資料庫中的 DynamoDB 資料流,並針對變更更新查詢資料庫。
Tools
工具
Amazon DynamoDB— Amazon DynamoDB 是一項完全受管的 NoSQL 資料庫服務,可提供快速且可預期的效能與無縫的可擴展性。
Amazon DynamoDB Streams— DynamoDB Streams 會擷取任何 DynamoDB 表格中依時間順序排序的項目層級修改。然後,它會儲存此資訊長達 24 小時。靜態加密會加密 DynamoDB 串流中的資料。
AWS Lambda— AWS Lambda 是一項運算服務,可支援執行程式碼,無需佈建或管理伺服器。Lambda 只有在需要時才會執行程式碼,可自動從每天數項請求擴展成每秒數千項請求。只需為使用的運算時間支付費用,一旦未執行程式碼,就會停止計費。
AWS 管理主控台— AWS 管理主控台是一種 Web 應用程式,其中會包含管理 AWS 服務的多種服務主控台。
Visual Studio 2019 社區版
— Visual Studio 2019 是整合式開發環境 (IDE)。開放原始碼貢獻者可免費使用社群版。在這種模式中,您將使用 Visual Studio 2019 社群版來開啟、編譯和執行範例程式碼。若為僅檢視,您可以使用任何文字編輯器或Visual Studio 程式碼。 AWS Toolkit for Visual Studio— AWS Toolkit for Visual Studio 是 Visual Studio IDE 的外掛程式。適用於 Visual Studio 的 AWS Toolkit 可讓您輕鬆開發、偵錯和部署使用 AWS 服務的 .NET 應用程式。
Code
附加範例程式碼。如需部署範例程式碼的指示,請參閱史詩區段。
Epics
任務 | 描述 | 所需技能 |
---|---|---|
開啟解決方案。 |
| 應用開發人員 |
建置解決方案。 | 開啟方案的內容 (按一下滑鼠右鍵) 功能表,然後選擇建置解決方案。這將構建和編譯解決方案中的所有項目。它應該編譯成功。 Visual Studio 解決方案資源管理器應該顯示目錄結構。
| 應用開發人員 |
任務 | 描述 | 所需技能 |
---|---|---|
提供登入資料。 | 如果您還沒有存取金鑰,請參閱相關資源區段。
| 應用程式開發人員, 資料工程師, DBA |
建置專案。 | 要建置專案,請開啟 (按一下滑鼠右鍵)使用者 .cqr..build專案,然後選擇建置。 | 應用程式開發人員, 資料工程師, DBA |
建置和填入資料表。 | 若要建置表格並填入種子資料,請開啟使用者 .cqr..build專案,然後選擇偵錯、啟動新執行個體。 | 應用程式開發人員, 資料工程師, DBA |
驗證表格結構和數據。 | 若要驗證,請導覽至AWS Explorer,然後展開Amazon DynamoDB。它應該顯示表。開啟每個表格以顯示範例資料。 | 應用程式開發人員, 資料工程師, DBA |
任務 | 描述 | 所需技能 |
---|---|---|
建置 CQRS 專案。 |
| 應用程式開發人員 |
建立事件來源專案。 |
| 應用程式開發人員 |
執行測試。 | 若要執行所有測試,請選擇檢視、測試 Explorer,然後選擇在檢視中執行所有測試。所有測試都應該通過,以綠色核取標記圖示表示。 | 應用程式開發人員 |
任務 | 描述 | 所需技能 |
---|---|---|
發佈第一個 Lambda 函數。 |
| 應用程式開發人員, 開發工程師 |
驗證函數上傳。 | (可選) 您可以透過導覽至 AWS 資源管理器並展開AWS Lambda。若要開啟測試視窗,請選擇 Lambda 函數 (按兩下)。 | 應用程式開發人員, 開發工程師 |
測試 Lambda 函數。 |
所有 CQRS Lambda 項目都在 | 應用程式開發人員, 開發工程師 |
發佈剩餘的函數。 | 針對以下專案重複先前的步驟:
| 應用程式開發人員, 開發工程師 |
任務 | 描述 | 所需技能 |
---|---|---|
發佈客戶和獎勵 Lambda 事件處理常式。 | 若要發佈每個事件處理常式,請依照前面的史詩中的步驟執行。 這些項目屬 | 應用開發人員 |
附加事件來源 Lambda 事件偵聽程式。 |
將接聽程式成功附加至 DynamoDB 表格後,就會顯示在 Lambda 設計工具頁面上。 | 應用開發人員 |
發佈並附加事件發佈 Lambda 函數。 | 若要發佈並附加 | 應用開發人員 |
任務 | 描述 | 所需技能 |
---|---|---|
測試串流和 Lambda 觸發器。 |
| 應用開發人員 |
使用 DynamodDB 獎勵查詢表進行驗證。 |
| 應用開發人員 |
使用 CloudWatch Logs 進行驗證。 |
| 應用開發人員 |
驗證事件供應商觸發程式。 | 若要驗證 | 應用開發人員 |
相關資源
References
影片
其他資訊
CQRS 和事件來源
CQRS
CQRS 模式將單一概念操作模型,例如數據訪問對象單一 CRUD(創建,讀取,更新,刪除)模型分開到命令和查詢操作模型中。指令模型是指變更狀態的任何作業,例如建立、更新或刪除。查詢模型是指傳回值的任何作業。

客戶 CRUD 模型包括以下界面:
Create Customer()
UpdateCustomer()
DeleteCustomer()
AddPoints()
RedeemPoints()
GetVIPCustomers()
GetCustomerList()
GetCustomerPoints()
隨著您的需求變得越來越複雜,您可以從這個單一模型的方法中移動。CQRS 使用命令模型和查詢模型來分離寫入和讀取數據的責任。這樣,數據就可以獨立維護和管理。由於責任明確分離,每個模型的增強功能不會影響其他模型。這種分離可以改善維護和效能,並減少應用程式成長的複雜性。

客戶命令模型中的介面:
Create Customer()
UpdateCustomer()
DeleteCustomer()
AddPoints()
RedeemPoints()
客戶查詢模型中的介面:
GetVIPCustomers()
GetCustomerList()
GetCustomerPoints()
GetMonthlyStatement()
如需範例程式碼,請參閱來源碼目錄。
CQRS 模式然後分離數據庫。這種解耦導致每個服務的完全獨立性,這是微服務架構的主要成分。

在 AWS 雲端中使用 CQRS,您可以進一步最佳化每項服務。例如,您可以設定不同的計算設定,或在無伺服器或容器型微服務之間進行選擇。您可以使用 Amazon ElastiCache 快取取代您的現場部署快取。如果您有內部部署發佈/訂閱訊息,您可以將其取代為 Amazon Simple Notification Service (Amazon SNS)。此外,您可以利用隨用隨付定價,以及只按使用量付費的各種 AWS 服務。
CQRS 包括以下好處:
獨立擴展-每個模型都可以調整其擴展策略,以滿足服務的需求和需求。與高效能應用程式類似,分離讀取和寫入可讓模型獨立調整以因應各種需求。您也可以新增或減少計算資源,以因應某個模型的延展性需求,而不會影響另一個模型。
獨立維護 — 查詢和命令模型的分離提高了模型的可維護性。您可以對一個模型進行程式碼變更和增強,而不會影響另一個模型。
安全性 — 將權限和原則套用至不同的模型以進行讀取和寫入更容易。
最佳化讀取 — 您可以定義針對查詢最佳化的結構描述。例如,您可以定義彙總資料的結構描述,定義事實表格的獨立結構描述。
整合 — CQRS 非常適合基於事件的程式設計模型。
受管理的複雜性-分離為查詢和命令模型適用於複雜的域。
使用 CQRS 時,請謹記以下警告:
CQRS 模式僅適用於應用程序的特定部分,而不適用於整個應用程序。如果在不符合模式的域上實現,它可以降低生產力,增加風險並引入複雜性。
此模式最適合具有讀取和寫入作業不平衡的常用模型。
對於大量讀取的應用程序,例如需要時間處理的大型報表,CQRS 可讓您選擇正確的數據庫,並創建一個結構描述來存儲您的聚合數據。如此一來,只處理報表資料一次並將其傾印在彙總表格中,藉此改善讀取和檢視報表的回應時間。
對於大量寫入的應用程式,您可以設定資料庫以進行寫入作業,並允許命令 Microservice 在寫入需求增加時獨立調整。如需範例,請參閱
AWS.APG.CQRSES.CommandRedeemRewardLambda
和AWS.APG.CQRSES.CommandAddRewardLambda
微服務。
事件來源
下一個步驟是使用事件 sourcing 在執行命令時同步處理查詢資料庫。例如,考量下列事件:
新增客戶獎勵點數,需要更新查詢資料庫中的客戶總計或彙總獎勵點數。
命令資料庫中會更新客戶的姓氏,因此需要更新查詢資料庫中的替代客戶資訊。
在傳統的 CRUD 模型中,您可以鎖定資料,直到它完成交易,以確保資料的一致性。在事件來源,數據通過發布一系列將被用戶更新其各自的數據消耗的事件進行同步。
事件來源模式可確保並記錄對資料採取的完整一系列動作,並透過一系列事件發佈。這些事件代表資料的一組變更,該事件的訂閱者必須處理以保持其記錄更新。這些事件會使用訂閱者,同步處理訂閱者的資料庫上的資料。在此情況下,這就是查詢資料庫。
下圖顯示 AWS 上與 CQRS 搭配使用的事件來源。

命令 Lambda 函式會執行寫入作業,例如,建立、更新或刪除。
查詢 Lambda 函數在資料庫上執行讀取作業,例如取得或選取。
此 Lambda 函數會處理命令資料庫中的 DynamoDB 資料流,並針對變更更新查詢資料庫。您也可以使用此功能將訊息發佈到 Amazon SNS,以便訂閱者可以處理資料。
(選擇性) Lambda 事件訂閱者會處理 Amazon SNS 發佈的訊息,並更新查詢資料庫。
(選擇性) Amazon SNS 會傳送寫入操作的電子郵件通知。
在 AWS 上,可以透過 DynamoDB Streams 同步查詢資料庫。DynamoDB 會擷取 DynamoDB 表格中依時間順序排序的項目層級修改,並在 24 小時內持久儲存資訊。
啟用 DynamoDB Streams 可讓資料庫發佈一系列事件,使事件來源模式成為可能。事件采購模式會添加事件訂戶。事件訂閱者應用程式會消耗事件,並根據訂閱者的責任進行處理。在上圖中,事件訂閱者會將變更推送至 Query DynamoDB 資料庫,以保持資料同步。Amazon SNS、訊息代理和事件訂閱者應用程式的使用可讓架構解耦。
事件來源具備下列優點:
交易資料的一致性
動作的可靠稽核記錄和歷史記錄,可用來監控資料中所採取的動作
允許分散式應用程式 (例如微服務) 在整個環境中同步處理其資料
每當狀態變化的可靠發布事件
重建或重新顯示過去的狀態
將事件交換從整合式應用程式遷移至微服務的鬆散耦合實體
減少同時更新所造成的衝突;事件來源可避免直接在資料存放區中更新物件的需求
解耦任務和事件的靈活性和可擴展性
External External
在單一事件中管理多個工作
使用事件來源時,請謹記以下警告:
因為來源訂閱者資料庫之間的更新資料有些延遲,唯一的方法來復原變更是將補償事件新增至事件存放區。
實施事件來源有一個學習曲線,因為它的編程風格的不同。
測試資料
成功部署後,請使用下列測試資料來測試 Lambda 函數。
指令建立客戶
{ "Id":1501, "Firstname":"John", "Lastname":"Done", "CompanyName":"AnyCompany", "Address": "USA", "VIP":true }
指令更新客戶
{ "Id":1501, "Firstname":"John", "Lastname":"Doe", "CompanyName":"Example Corp.", "Address": "Seattle, USA", "VIP":true }
指令刪除客戶
輸入客戶識別碼作為請求資料。例如,如果客戶識別碼為 151,請輸入 151 作為請求資料。
151
查詢客戶清單
這是空白的。當它被調用時,它會返回所有客戶。
指令新增獎勵
這將為 ID 1 (Richard) 的客戶增加 40 點。
{ "Id":10101, "CustomerId":1, "Points":40 }
指揮官獎勵
ID 1 (Richard) 的客戶將會扣除 15 分。
{ "Id":10110, "CustomerId":1, "Points":15 }
查詢獎勵
輸入客戶的 ID。例如,輸入 1 表示理查德,輸入 2 表示阿納夫,輸入 3 表示雪莉。
2
來源碼目錄
使用下表做為 Visual Studio 解決方案的目錄結構的指南。
CQRS 內部部署程式碼範例解決方案目錄

客戶 CRUD 模式
CQRS 內部部署程式碼範例\ CRUD 模型\ AW.APG.CQRSES.DAL 專案
客戶 CRUD 模型的 CQRS 版本
客戶指令:
CQRS On-Premises Code Sample\CQRS Model\Command Microservice\AWS.APG.CQRSES.Command
project客戶查詢:
CQRS On-Premises Code Sample\CQRS Model\Query Microservice\AWS.APG.CQRSES.Query
project
命令和查詢微服務
命令微服務位於解決方案文件夾下CQRS On-Premises Code Sample\CQRS Model\Command Microservice
:
AWS.APG.CQRSES.CommandMicroservice
ASP.NET 核心 API 專案充當消費者與服務互動的入口點。AWS.APG.CQRSES.Command
.NET 核心項目是託管命令相關的對象和接口的對象。
查詢微服務位於解決方案文件夾下CQRS On-Premises Code Sample\CQRS Model\Query Microservice
:
AWS.APG.CQRSES.QueryMicroservice
ASP.NET 核心 API 專案充當消費者與服務互動的入口點。AWS.APG.CQRSES.Query
.NET 核心項目是託管查詢相關的對象和接口的對象。
CQRS AWS 無伺服器程式碼解決方案目錄

此程式碼是使用 AWS 無伺服器服務的現場部署程式碼的 AWS 版本。
在 C# .NET 核心中,每個 Lambda 函數由一個 .NET 核心項目表示。在此模式的示例代碼中,命令和查詢模型中的每個接口都有一個單獨的項目。
使用 AWS 服務的 CQRS
您可以找到使用 AWS 無伺服器服務的 CQRS 根解決方案目錄位於CQRS AWS Serverless\CQRS
folder。此範例包括兩個型號:客戶與獎勵。
客戶與獎勵的 Lambda 函數指令位於CQRS\Command Microservice\Customer
和CQRS\Command Microservice\Reward
資料夾。它們包含以下 Lambda 項目:
客戶指令:
CommandCreateLambda
、CommandDeleteLambda
,以及CommandUpdateLambda
獎勵命令:
CommandAddRewardLambda
和CommandRedeemRewardLambda
客戶和獎勵的查詢 Lambda 函數位於CQRS\Query Microservice\Customer
和CQRS\QueryMicroservice\Reward
資料夾。它們包含QueryCustomerListLambda
和QueryRewardLambda
Lambda 專案。
CQRS 測試專案
該測試項目是CQRS\Tests
folder。此專案包含測試指令碼,可自動測試 CQRS Lambda 函式。
使用 AWS 服務的事件來源
下列 Lambda 事件處理常式是由「客戶」和「獎勵」DynamoDB 資料流初始化,以處理及同步查詢表格中的資料。
所以此
EventSourceCustomer
Lambda 函數對應至客戶資料表 (cqrses-customer-cmd
) DynamoDB 串流。所以此
EventSourceReward
Lambda 函數映射到獎勵表(cqrses-reward-cmd
) DynamoDB 串流。