切實有效的三個步驟:如何通過劃分有界上下文設計微服務? - Robert Reppel
通過有界上下文和無所不在的語言,實現高聚合低關聯並獲得服務邊界。
是什麼讓系統邊界“乾淨整潔”?
我們通常使用的軟體都是基於狀態機的系統:像交通燈一樣,changeLight()的結果取決於先前的狀態是“紅色”,“琥珀色”還是“綠色”。
當前狀態取決於過去發生的事情(儲存在諸如“資料庫”和/或“事件日誌”之類的事物中)。
任何此類機器的未來狀態始終取決於:
- 它目前的狀態
- 收到的狀態更改指令(“命令”)。
- 命令的引數。
如果無法保證將命令和狀態封裝在一起,那麼就可能hack破解這個狀態機,不通過命令直接修改當前狀態,這也稱為稱為副作用。副作用會導致錯誤。它們可以導致主要的迴歸測試工作並減緩釋出週期。他們甚至導致官僚主義。(“這次停機幾乎殺死了我們。從現在開始,沒有人在沒有簽字的情況下進行部署。”)
具有“漂亮和乾淨”系統邊界的服務才具有凝聚力。將屬於一起的東西在程式碼中放在一起,共享一個目標,不要將不屬於一起的概念和功能混合在一起。
這樣低耦合的服務才具有在其自己的資料儲存和命令引數中做出決策所需的所有資訊。它不會做出錯誤的決定或被拒絕,因為它不會依賴於呼叫另一個可能不可用或發生故障的外部服務。
讓我們通過一個例子,通過使用業務領域事件和領域驅動設計的兩個概念:“無處不在的統一語言”和“有界上下文”,我們如何構建更容易維護和更少副作用的免費軟體:
第1步 - 溝通和理解:事件風暴
事件風暴是一個相當簡單的想法:讓人們進入一個房間並讓他們通過一個系統描述各種工作流程:如果這一年內發生了什麼,發生了什麼業務活動(”訂單已下單“,”付款已處理“, “物品運送”,......),將會發生什麼,以什麼順序發生?
在這裡,我們將使用自行車共享應用程式,該應用程式是在之前的部落格文章中從實際的真實世界系統進行逆向工程。事件風暴同樣可以很好地分享和理解新系統的需求以及探索現有的遺留程式碼。
傳統上,事件風暴是通過牆上的便籤貼完成的。而我們正在使用的是故事風暴StoryStream及基於文字的“事件風暴語言”(ESL)。StoryStream目前處於早期測試階段。
事件風暴是一個強大的工具,因為它可以削減技術術語,並將參與者集中在業務成果上,用簡單的英語描述,適用於建模服務和規劃技術實施。
第2步 - 服務邊界:將所屬的組合在一起
忘記所有的技術考慮因素,檢視領域事件,命令等,並將它們歸類,這裡介紹一個詞語拖拉歸類方法,可以通過Kubel來完成,Kubel是一個用於探索有界上下文的實驗性開源工具。
將以下內容複製並貼上到https://robertreppel.github.io/kubel/中:
/// Bike Sharing /// Locations Set Up Bike Sharing Location-> : locationId, lat, long, name Location Added Locations* locationId, lat, long, name Add Bike To Location-> bikeId, locationId Bike Added : bikeId, locationId // "Bike Added" could happen many times, depending on how many bikes are kept at this location. Location* : list of bikes at location /// Register User Register-> email Registration Started : userId, email Pending Registrations* Confirm Registration-> confirmationCode Registration Confirmed : userId Confirmed Registrations* Set Password-> userId, password Password Updated : passwordHash Add Payment Method-> Payment Method Added : creditCardToken, last4Digits My Profile* : userId, email, creditCardToken, last4Digits Charge Deposit-> Payment Processed Deposit Received // Deposit received only occurs if payment processing succeeded.The "Charge Deposit" command may be (e.g.) issued by a process controller "microservice" which issues it as a result of having received "Registration Confirmed" and "Payment Method Added" events. /// Ride Unlock Bike-> locationId, bikeId Bike Unlocked : bikeId Ride Started : rideId, bikeId Rides In Progress* : Bike Removed : locationId, bikeId Lock Bike-> bikeId, bikeLocationLat, bikeLocationLong Bike Locked Bike Returned // Only mark bike as "returned" if it's within 10 meters of a location. Bike Added: bikeId, locationId /// User deletes account Rides in Progress* : userId, bikeId, startLocationId, startTime // Registration cannot be deleted if a user is currently on a ride Delete Registration-> userId Deposit Refunded : userId, amount, date Registration Deleted /// Remove bike sharing location Remove Location-> locationId=123423 Bike Removed : locationId=123423, bikeId Bike Added : locationId=123456, bikeId Location Removed : locationId // "Bike Removed" for each bike at the location which is being removed (123423), followed by "Bike Added" for to another location, e.g. 123456. Maybe one location (e.g. 123456) could be the depot or maintenance location? |
點選“Generate Vocabulary”將文字輸入轉換為可拖動的詞彙項。(中文也可以),將詞彙表拖動到表示不同有界上下文的組中。每個這樣的組都是作為單獨服務實現的候選者。試試看。當我們這樣做時,我們的結果:
這樣我們有五種潛在服務:
- 使用者認證/授權
- 乘客Rides
- 地點
- 交付過程
- 存款
第3步 - 評估設計:Monkey Wrenching
我們有候選服務,但我們怎麼知道他們是否有合適的微服務邊界?關閉它們。
混沌工程通常用於測試實時IT系統的彈性,但在設計早期評估軟體架構決策的業務影響時,這一技巧也很有用。做一個思想實驗......
關閉位置服務:
- 人們仍然可以註冊,付款和存款,並檢視自行車。
- 在位置顯示的可用自行車數量可能不正確,導致使用者誤導可用性。
- 支援人員的自行車庫存管理已不再可用。
關閉付款處理:
- 仍然可以開始註冊自行車共享服務並登入,但是檢查自行車對新使用者不起作用,因為不能進行損壞賠錢。
- 我們設計付款處理是為了租用自行車過長,超期限,則現有使用者仍可能在該項服務停止後還能checkou自行車。業務風險是:一些付款請求將失敗,導致免費騎車和收入損失。這可能是不可接受的。
- 使用者仍然可以檢視位置和可用的自行車數量。
不可用的服務會影響終端使用者體驗。設計時的“Monkey Wrenching”使得中斷的影響明確,以便業務利益相關者可以進行必要的權衡。
某些影響是可以接受的,可以通過(例如)客戶支援來處理。其他(例如上面的批量支付處理能力)需要技術緩解以及隨之而來的資源和計劃。
一個好的架構可以在服務失敗時優雅地分解。是什麼決定了可接受的“優雅”水準?是業務決策,而不是技術決策。
結論
我們已經看到了:“知道什麼屬於一起的自然能力”是如何用於建立服務邊界,這使得鬆散耦合,內聚和彈性系統。該技術基於兩個領域驅動設計概念:“無處不在的語言”和“有界上下文”。近年來,我們使用這種方法在實際專案中建立系統邊界,並且執行良好。
使用語言而不是技術標準來確定系統邊界的優勢在於,在確定程式碼應該存在的位置時,它會產生自然,直觀的“引導圍欄guide fences”。
相關文章
- 如何劃分有界上下文? - nick
- 一個微服務對應一個有界的上下文嗎?微服務
- 關於有界上下文和微服務的關係以及它們的劃分粒度 - Alberto Brandolini微服務
- 如何劃分微服務微服務
- 5個步驟實現有效的DevSecOpsdev
- 成功實施BPM計劃的5個步驟 - ProServROS
- 如何權衡設計可擴充套件的有界上下文? (mathiasverraes)套件
- 有效的微服務:10 個最佳實踐微服務
- 實現安全設計模式的7個步驟設計模式
- 資料和行為與有界上下文、微服務的關係 - Alberto Brandolini微服務
- 劃分微服務邊界的5個特徵微服務特徵
- 成功備戰微服務的5個準備步驟微服務
- 有效採購流程的7個步驟
- 單體轉變到微服務之前採取DDD的三個步驟 - Jim Rottinger微服務
- 微服務劃分的姿勢微服務
- 網站設計的八個步驟網站
- 實施 GitOps 的三個關鍵步驟Git
- 如何設計出“好看”的UI介面(二):4個步驟,搞定介面設計UI
- 環境互動:通過空間劃分的關卡設計
- 微服務劃分原則微服務
- 專案管理計劃制定的四個關鍵步驟專案管理
- 軟體結構設計,具體分為幾個步驟?
- 資料庫設計中的6個最佳實踐步驟資料庫
- 如何設計一個容錯的微服務架構微服務架構
- [譯]如何通過7個簡單步驟保護您的Linux伺服器Linux伺服器
- 通過Dapr實現一個簡單的基於.net的微服務電商系統(七)——一步一步教你如何擼Dapr之服務限流微服務
- 通過Dapr實現一個簡單的基於.net的微服務電商系統(六)——一步一步教你如何擼Dapr之Actor服務微服務
- 真正的敏捷是根據DDD有界上下文劃分其團隊組織結構 - allenholub敏捷
- 幽默:“通過128個簡單的步驟學習Kubernetes!” - iamdevloperdev
- 自媒體人如何打造人設?三個步驟教你打造人設!
- 設計微服務的最佳實踐微服務
- 使用設計畫布發現和建模有界上下文 - Nick Tune
- 從三方面出發瞭解城市規劃館設計的步驟
- 有效的製造運營管理策略的10個步驟
- 通過Dapr實現一個簡單的基於.net的微服務電商系統(十)——一步一步教你如何擼Dapr之繫結微服務
- Redis如何簡化實現微服務的設計模式 – thenewstackRedis微服務設計模式
- 4 個步驟啟動VOC(客戶之聲)計劃
- 數字展廳設計的三大製作步驟