切實有效的三個步驟:如何通過劃分有界上下文設計微服務? - Robert Reppel

banq發表於2019-07-31

通過有界上下文和無所不在的語言,實現高聚合低關聯並獲得服務邊界。

是什麼讓系統邊界“乾淨整潔”?

我們通常使用的軟體都是基於狀態機的系統:像交通燈一樣,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”將文字輸入轉換為可拖動的詞彙項。(中文也可以),將詞彙表拖動到表示不同有界上下文的組中。每個這樣的組都是作為單獨服務實現的候選者。試試看。當我們這樣做時,我們的結果:

切實有效的三個步驟:如何通過劃分有界上下文設計微服務? - Robert Reppel

這樣我們有五種潛在服務:

  • 使用者認證/授權
  • 乘客Rides
  • 地點
  • 交付過程
  • 存款

第3步 - 評估設計:Monkey Wrenching

我們有候選服務,但我們怎麼知道他們是否有合適的微服務邊界?關閉它們。

混沌工程通常用於測試實時IT系統的彈性,但在設計早期評估軟體架構決策的業務影響時,這一技巧也很有用。做一個思想實驗......

關閉位置服務:

  • 人們仍然可以註冊,付款和存款,並檢視自行車。
  • 在位置顯示的可用自行車數量可能不正確,導致使用者誤導可用性。
  • 支援人員的自行車庫存管理已不再可用。

關閉付款處理:

  • 仍然可以開始註冊自行車共享服務並登入,但是檢查自行車對新使用者不起作用,因為不能進行損壞賠錢。
  • 我們設計付款處理是為了租用自行車過長,超期限,則現有使用者仍可能在該項服務停止後還能checkou自行車。業務風險是:一些付款請求將失敗,導致免費騎車和收入損失。這可能是不可接受的。
  • 使用者仍然可以檢視位置和可用的自行車數量。

不可用的服務會影響終端使用者體驗。設計時的“Monkey Wrenching”使得中斷的影響明確,以便業務利益相關者可以進行必要的權衡。

某些影響是可以接受的,可以通過(例如)客戶支援來處理。其他(例如上面的批量支付處理能力)需要技術緩解以及隨之而來的資源和計劃。

一個好的架構可以在服務失敗時優雅地分解。是什麼決定了可接受的“優雅”水準?是業務決策,而不是技術決策。

結論

我們已經看到了:“知道什麼屬於一起的自然能力”是如何用於建立服務邊界,這使得鬆散耦合,內聚和彈性系統。該技術基於兩個領域驅動設計概念:“無處不在的語言”和“有界上下文”。近年來,我們使用這種方法在實際專案中建立系統邊界,並且執行良好。

使用語言而不是技術標準來確定系統邊界的優勢在於,在確定程式碼應該存在的位置時,它會產生自然,直觀的“引導圍欄guide fences”。

 

相關文章