共用方式為


使用領域分析進行微服務建模

微服務最大的挑戰之一是定義個別服務的界限。 一般規則是服務應該執行「一件事」,但將規則付諸實踐需要仔細思考。 沒有機械工藝將產生“正確的”設計。 您必須深入思考您的商務領域、需求、架構特性(也稱為非功能性需求),以及目標。 否則,您最終可能會有一個不合時宜的設計,以呈現一些不想要的特性,例如服務之間的隱藏相依性、緊密結合或設計不佳的介面。 本文說明設計微服務的網域驅動方法。 評估服務界限是不斷演進工作負載的工作。 有時候評估會產生重新定義的現有界限定義,而需要額外的應用程式開發以配合變更。

本文使用無人機遞送服務作為執行中的範例。 您可以在這裡深入瞭解案例和對應的參考實作

簡介

微服務應針對商務功能進行設計,而不是水準層,例如數據存取或傳訊。 此外,它們應該具有鬆散結合和高功能凝聚力。 如果您可以變更一個服務,而不需要同時更新其他服務,微服務就會 鬆散結合 。 如果微服務具有單一且定義完善的用途,例如管理用戶帳戶或追蹤傳遞歷程記錄,微服務就會 一致 。 服務應該封裝領域知識,並從用戶端抽象化該知識。 例如,客戶端應該能夠在不知道排程演算法的詳細數據或無人機機隊管理方式的情況下排程無人機。 必須為每個微服務定義架構特性,以符合其領域考慮,而不是針對整個系統定義。 例如,面向客戶的微服務可能需要有效能、可用性、容錯、安全性、可測試性和靈活度。 後端微服務可能只需要容錯和安全性。 如果微服務彼此有同步通訊,它們之間的相依性通常會產生共用相同架構特性的需求。

領域導向的設計 (DDD) 可提供一套架構,讓您設計良好的微服務。 DDD 有兩個不同的階段:「策略」階段和「戰術」階段。 在策略性 DDD 中,您會定義系統的大規模結構。 策略性 DDD 有助於確保您的架構持續聚焦在商務功能上。 戰術性 DDD 提供了一組設計模式,您可以用來建立領域模型。 這些模式包括實體、彙總和領域服務。 這些戰術性模式可協助您設計既是鬆散地結合,又具有一致性的微服務。

網域驅動設計 (DDD) 程式的圖表

在本文中和下一步中,我們將逐步解說下列步驟,將它們套用至無人機遞送應用程式:

  1. 先從分析業務領域開始,以了解應用程式的功能需求。 此步驟結果是領域的非正式描述,可以精簡成更加正式的一套領域模型。

  2. 接下來,定義 網域的限定內容 。 每個限界內容都會包含領域模型,後者代表較大應用程式的特定子領域。

  3. 在限界內容中,套用戰術性 DDD 模式來定義實體、彙總和領域服務。

  4. 使用上一個步驟的結果來識別應用程式中的微服務。

在本文中,我們將討論前三個步驟,主要涉及 DDD。 在下一篇文章中,我們將識別微服務。 不過,請務必記住 DDD 是反覆且持續的過程。 服務界限不是固定在石頭上。 隨著應用程式的發展,您可能會決定將服務分成數個較小的服務。

注意

此文章不會顯示完整和全方位的領域分析。 我們刻意將範例保持簡短,以說明要點。 如需有關 DDD 的詳細背景資訊,我們推薦由 Eric Evans 所著、首先介紹 DDD 一詞的《Domain-Driven Design (領域導向的設計)》一書。 另一本良好的參考是 Vaughn Vernon 所著的《Implementing Domain-Driven Design》(實作領域驅動設計)。

案例:無人機遞送

Fabrikam, Inc. 正在啟動無人機遞送服務。 該公司管理著一批無人機飛機。 企業會註冊此服務,而使用者可要求無人機收取貨物進行遞送。 當客戶排程取貨時,後端系統會指派無人機,並以預估的交貨時間通知使用者。 在遞送過程中,客戶可以使用持續更新的 ETA 來追蹤無人機的位置。

此案例牽涉到相當複雜的領域。 部分商務考慮包括排程無人機、追蹤套件、管理用戶帳戶,以及儲存和分析歷程記錄數據。 此外,Fabrikam 想要快速上市,然後快速反覆運算,並新增新功能和功能。 應用程式需要以雲端規模運作,具有高服務等級目標 (SLO)。 Fabrikam 也預期系統的不同部分對於數據儲存和查詢會有非常不同的需求。 所有這些考慮都會導致 Fabrikam 選擇無人機傳遞應用程式的微服務架構。

分析網域

使用 DDD 方法可協助您設計微服務,讓每個服務形成符合功能商務需求的自然需求。 它可協助您避免讓組織界限或技術選擇決定您的設計陷阱。

在撰寫任何程序代碼之前,您需要您正在建立之系統的鳥眼檢視。 DDD 首先將商務領域模型化,並建立 領域模型。 領域模型是業務領域的抽象模型。 它會提煉和組織領域知識,併為開發人員和領域專家提供通用語言。

先從對應所有商務功能及其連線開始。 這可能是共同作業的工作,牽涉到領域專家、軟體架構設計人員與其他專案關係人。 您不需要使用任何特定的形式。 只需草繪圖表或在白板上繪圖即可。

當您填入圖表時,可能會開始識別離散子域。 有哪些功能是密切相關的? 哪些功能是業務核心?又有哪些功能會提供附屬服務? 什麼是相依性關係圖? 在此初始階段,您不必擔心技術或實作細節。 話雖如此,您仍應注意應用程式需要在何處與外部系統 (例如 CRM、付款處理或計費系統) 整合。

範例:無人機遞送應用程式

在一些初始領域分析之後,Fabrikam 小組提出了一個粗略的草圖,描繪了無人機遞送領域。

無人機遞送網域的圖表

  • 出貨 會放在圖表的中心,因為它是業務的核心。 圖表中其他所有專案都存在,可啟用這項功能。
  • 無人機管理 也是業務的核心。 與無人機管理密切相關的功能包括 無人機維修 ,並使用 預測性分析 預測無人機何時需要維護和維護。
  • ETA 分析 提供取貨和遞送的時間估計值。
  • 如果無法完全由無人機運送包裹,第三方運輸 將使應用程式能夠排程替代運輸方法。
  • 無人機共用 是核心業務可能的延伸。 該公司在特定時間可能會有多餘的無人機容量,並可能出租那些本來會閑置的無人機。 這項功能不會在初始版本中。
  • 視頻監控 是公司稍後可能擴展的另一個領域。
  • 用戶帳戶發票開立通話中心 是支援核心業務的子域。

請注意,在這個過程中,我們尚未做出任何關於實作或技術的決定。 某些子系統可能涉及外部軟體系統或第三方服務。 即便如此,應用程式也需要與這些系統和服務互動,因此請務必將它們包含在定義域模型中。

注意

當應用程式相依於外部系統時,外部系統的數據架構或API可能會外洩至您的應用程式,最終危及架構設計。 這特別適用於舊版系統可能未遵循新式最佳做法,而且可能會使用卷積的數據架構或過時的 API。 在此情況下,在這些外部系統與應用程式之間必須有妥善定義的界限。 請考慮針對此目的使用 Strangler Fig 模式反腐層模式

定義限界內容

領域模型會包括真實世界中事物的代表 — 使用者、無人機、包裹等。 但這並不表示針對相同的事物,系統的每個部分都需要使用相同的代表。

例如,處理無人機維修和預測分析的子系統必須代表無人機的許多實體特性,例如其維護歷程記錄、里程、年齡、型號、效能特性等等。 但在排程遞送時,我們不會在意這些特性。 排程子系統只需要知道無人機是否可用,以及用於取貨和遞送的ETA。

如果我們嘗試為這兩個子系統建立單一模型,就會變得不必要的複雜。 模型在一段時間內發展也變得更加困難,因為任何變更都需要滿足多個小組在不同的子系統上工作。 因此,最好在兩個不同的內容中設計代表相同真實世界實體(在此案例中為無人機)的不同模型。 每一個模型都只包含在其特定內容中相關的功能和屬性。

這是限定內容的 DDD 概念發揮作用的地方。 限界內容只是領域內的界限,系統會在此套用特定的領域模型。 對照先前的圖表,我們可以根據各種功能是否會共用單一的領域模型,來將功能分組。

限定內容的圖表

限定內容不一定彼此隔離。 在此圖表中,連接限定內容的實線代表兩個限定內容互動的位置。 例如,出貨取決於使用者帳戶來取得客戶的相關信息,以及無人機管理以排程車隊中的無人機。

在網域驅動設計一書中,Eric Evans 描述在與另一個限定內容互動時,維護領域模型完整性的數種模式。 微服務的主要原則之一是服務會透過定義完善的 API 進行通訊。 此方法對應至埃文斯呼叫 Open Host Service 和已發佈語言的兩種模式。 Open Host Service 的概念是子系統會定義正式通訊協定(API),讓其他子系統與其通訊。 已發佈語言會藉由以其他小組可用來撰寫用戶端的窗體發佈 API 來擴充此概念。 在設計微服務 API 一文中,我們會討論如何使用 OpenAPI 規格(先前稱為 Swagger)來定義 REST API 的語言無關介面描述,以 JSON 或 YAML 格式表示。

在此旅程的其餘部分,我們將著重於出貨範圍內容。

下一步

完成定義域分析之後,下一個步驟是套用戰術 DDD,以更精確地定義您的領域模型。