最近試著實作Microservices的SAGA Orchestration Pattern,以建立訂單和更新(扣減)庫存數量來練習,本篇為循序圖。
元件說明:
- client - 客戶端,例如前端或另一個系統。
- create_order_usecase - 在這負責建立create_order_orchestrator物件及編排流程邏輯的地方。
- create_order_orchestrator - 負責執行編排流程邏輯的物件,包含正向與補償(compensation/rollback)動作,即SAGA Orchestration模式的主要角色,將分散各處業務流程及交易集中管理。本身在每個動作完成後會變更狀態,內含有限狀態機來處理狀態的轉移。
- mq - 即Messsage Queue,訊息隊列系統,例如RabbitMQ。用來解耦多個服務實現非同步分散處理。
- order_handler - 也可稱為order service,負責處理與訂單(order)有關的微服務。
- inventory_handler - 也可稱為inventory service,負責處理與庫存(inventory)有關的微服務。
- db - 資料庫,假設order和inventory資料表是存在不同兩個資料庫。
邏輯很簡單,建立訂單->更新庫存->訂單建立完成,但因為是分散式服務所以無法用單一個資料庫交易來達成原子性操作以滿足完整性,且失敗時無法利用資料庫的回滾(rollback)機制,這也是SAGA pattern存在的目的,又於分散式/微服務系統的特性無法保證原子性,所以需要補償機制/流程來確保資料一致性/完整性。
上圖因為忘記(偷懶)沒有把補償機制/流程繪製出來。
實作參考「Golang SAGA Orchestration Pattern 建立訂單練習」。
本圖以PlantUML語法來繪製,原始語法如下。
@startuml
participant client
participant create_order_usecase
participant create_order_orchestrator
participant mq
participant order_handler
participant inventory_handler
database db
skinparam sequenceMessageAlign center
skinparam ParticipantPadding 50
client ->> create_order_usecase : create order request
activate create_order_usecase
create_order_usecase -->> client : 202 accepted
create_order_usecase -> create_order_orchestrator : create new create_order_orchestrator
activate create_order_orchestrator
note over create_order_orchestrator: state: start
create_order_orchestrator ->> mq : 'create_order' event message
activate mq
mq -> order_handler
activate order_handler
order_handler -> db : INSERT INTO order\nwith state 'creating'
activate db
db --> order_handler
note right: order.state='created'
deactivate db
order_handler -> mq : 'order_created' event message
deactivate order_handler
mq -> create_order_orchestrator
note over create_order_orchestrator: state: order_created
create_order_orchestrator -> mq: 'update_inventory' event message
mq -> inventory_handler
activate inventory_handler
inventory_handler -> db: UPDATE inventory stock quantity
activate db
db --> inventory_handler
deactivate db
inventory_handler -> mq: 'inventory_updated' event message
deactivate inventory_handler
mq -> create_order_orchestrator
note over create_order_orchestrator: state: inventory_updated
create_order_orchestrator -> mq: 'update_order_state' event message
mq -> order_handler
activate order_handler
order_handler -> db: UPDATE order state with 'created'
activate db
db --> order_handler
note right: order.state='created'
deactivate db
order_handler -> mq: 'order_updated' event message
deactivate order_handler
mq -> create_order_orchestrator
deactivate mq
note over create_order_orchestrator: state: done
deactivate order_handler
create_order_orchestrator --> create_order_usecase
deactivate create_order_orchestrator
create_order_usecase -> client: order created
deactivate create_order_usecase
@enduml
沒有留言:
張貼留言