1. 程式人生 > >【詳解】以銀行零售業務為例,一個案例說清楚視覺化微服務架構_Kubernetes中文社群

【詳解】以銀行零售業務為例,一個案例說清楚視覺化微服務架構_Kubernetes中文社群

Part 1: API設計和策略

軟體系統的複雜性是一個很痛苦的問題,而且無法避免。Fred Brooks將複雜性描述為,軟體系統解決業務問題所固有的本質複雜性,以及實施該解決方案所帶來的偶發複雜性。

隨著與採用“API優先”工程實踐和微服務架構的組織進行更密切的合作,我發現這種描述越來越有用。首先,通過這種方式分離複雜性,它允許架構師和工程師專注於最小化系統的偶發複雜性。

與微服務相關的技術創新有很大幫助:容器,自動化工具和API管理平臺。但我真正喜歡這種複雜性劃分的原因是,它幫助我們認清一個事實:任何技術都不能降低系統的本質複雜性。

“開發軟體產品的許多經典問題源於這種本質的複雜性,其非線性隨著規模的增加而增加。” – 出自Fred Brooks著《No Silver Bullet—Essence & Accident in Software Engineering》

但是,我們能做的至少是理解和記錄一個系統的本質複雜性。對於大多數技術人員來說,有效完成這一任務很重要,因為系統的本質複雜性不包括解決方案中使用的底層技術。

系統本質複雜性定義的本質要素是系統執行的任務和功能,以及執行所需的物件和互動。為了優化這種定義的認知負荷,將此定義表達為視覺模型也是很自然的。即使在視覺化的情況下,軟體架構師仍然努力保持模型中的元素不受技術限制,並且保持一致。

Eric Evans的領域驅動設計(Domain-Driven Design ,DDD)方法論突出的原因是,它提供了一種視覺化定義軟體系統本質複雜性的方法。特別是,顯示域,子域,有界上下文及其相互關係的上下文對映,與我見過的以有效方式說明本質複雜性的任何方法都非常接近。 UML意在提供一種用於定義與技術無關的應用程式描述的手段,但它的許多模型自然偏向於面向物件的根源。事實上,如果你深入DDD工具箱,我認為你會遇到同樣的偏見。

我在定義一個互連微服務系統時,使用了DDD上下文對映的派生。將在未來的文章中詳細介紹這種方法。

示例上下文對映

為什麼理解和記錄軟體系統的本質複雜性很重要,這與微服務有什麼關係?隨著微服務系統的發展和演變,其許多好處來自於服務本身的凝聚力。PhilCalçado在他的部落格文章“微服務與分散式物件的第一定律(Microservices & the First Law of Distributed Objects)”中強調了這一需求。凝聚力是確定服務邊界的產物,這是模擬系統本質複雜性的必要步驟。

有趣的是,與Brooks所描述的複雜性似乎是矛盾的,微服務系統的技術無關上下文對映在某種程度上與它的實現的拓撲結構是同構的,遠遠超過一整套單體應用的拓撲。這可能是一個巧合,也表明我們正在採用這種微服務架構方法。

Part 2:設計微服務系統

最近我一直在與許多大型組織合作,幫助他們理解並實現Web API和微服務體系結構的價值。在這項工作中,我看到這些組織一直在努力於,如何定義企業裡微服務之間的最佳邊界。這是一個已知的問題,但沒有解決。雖然關於凝聚式服務(cohesive services)的價值和有界上下文已經寫了很多,但如何實際識別這些內容似乎沒有指導意義。

這個問題的一個原因是,試圖確定服務邊界的人是技術人員,他們天生就在尋找技術解決方案,但是定義凝聚力和能力一致性的服務邊界(cohesive, capability-aligned service boundaries)卻需要領域專家。從根本上說,這應該是一種建模練習,它獨立於任何技術的覆蓋。然而,即使那些有意識地採用了技術無關建模方法的組織,也一直在努力定義服務邊界。

發生這種情況的部分原因是,最流行的軟體建模方法往往存在實施偏差。例如,領域驅動設計(DDD)傾向於面向物件的程式設計,而UML偏向資料建模的角度。除此之外,業界還沒有就如何直觀地描繪微服務系統模型達成共識,諸如應該描述哪些元件,應該如何表示關係,應該使用什麼術語,更不用說這其中的任何工具。

不過,所有的希望都不會丟失。 DDD的一些概念,最明顯的是“有界上下文”( bounded contexts)的概念,已經獲得了普及,並啟動了關於服務邊界定義的行業對話。重要的是,DDD方法論中更高層次的抽象,包括域,子域,有界上下文,聚合(aggregates),上下文對映,都是技術不可知和模型為中心的。

理解系統的方法是關注元件之間的關係,如果想要一個微服務系統的基本表示,不需要比上下文對映更深入。因此,也許我們可以使用DDD上下文對映作為視覺化微服務系統的起點。

即使在上下文對映層面,大型組織的完整服務系統也是不可理解的。因此,為了使上下文對映有用,為上下文對映本身設定上下文非常重要。這種上下文可以是特定整體應用程式的分解,或特定計劃的服務互動。連貫地構建一個大型組織的微服務系統的唯一方法就是,逐條地,上下文地進行。

微服務上下文對映示例

來看一個例子。一家大型零售銀行希望引入以客戶為中心的服務,以實現留住客戶的戰略目標。它希望提供一種新的以客戶為中心的支付解決方案,允許客戶根據他們與銀行的關係(他們的賬戶,投資,資產,互動模式)進行購買,而不是將授權決策基於一個特定帳戶。

零售銀行業務本身就是一個複雜的業務領域。客戶,產品和服務渠道(分支機構,網上銀行,銷售點)等實體之間存在相互關係,以及與財務透明度和資料隱私相關的強制性規定。因此,儘管這種新的支付服務背後的想法很直觀,但它卻呈現出一個複雜的問題空間。那麼從哪裡開始呢?

繼DDD方法鬆散之後,我們可以首先將零售銀行業務領域劃分為子域。作為一個起點,並遵循康威法則的必然性,可以從組成零售銀行的組織單位開始,並與以客戶為中心的支付解決方案相關。這些是:

這些子域可以通過以下方式進行視覺化描述:

這給了我們一個考慮如何分類建立以客戶為中心的支付解決方案服務的起點。自助銀行和客戶與卡片管理子域名突出顯示,因為它們已被確定為解決方案的關鍵子域名。使用DDD的“語言邊界”概念,顯然有一些有界上下文出現在子域中。

在自助銀行內部,有兩種截然不同的有界上下文。網上銀行渠道與手機銀行渠道有共同的語言,他們都提供個性化的客戶體驗,而支援移動渠道的應用程式則是由網路渠道構建和共享元件。我們將這種情況稱為context Online Banking。另一方面,銷售點具有獨特的語言,更多地集中在裝置管理和商家關係上。我們將稱之為銷售點(context Point of Sale)。

客戶與卡片管理甚至更加分散。核心客戶資訊,包括銀行客戶的權威列表,他們的聯絡資訊和產品庫,形成了一個獨特的詞彙表,我們稱之為客戶資訊有界的上下文。另一種不同的語言被用來描述卡功能,這主要與支付活動有關。這是“消費者支付和交易”上下文。最後,還有一個客戶身份上下文專注於客戶安全和訪問控制。

產品子域名對於此付款解決方案並不重要,但值得注意的是零售貸款和貸款子域劃分為單獨的PLC賬戶和信用卡上下文。完整的相關有界上下文如下所示:

在確定了有界上下文之後,現在可以考慮顧客將在其中使用哪些服務。如前所述,網上銀行有兩種服務消費者:網上銀行web App和手機銀行App。新的支付解決方案也將通過銷售點的POS網路收到的訊息請求所消耗。

客戶身份上下文必須提供客戶身份驗證服務,以確保只有合適的請求者才能訪問新的付款服務。客戶資訊背景包含客戶和產品持有人之間的交叉參考,因此需要核心客戶資訊服務來為新的支付解決方案提供這些資料。

除此之外,跟蹤客戶財務活動,與其產品持有相關的財務事件,將有助於做出授權決策。因此,客戶活動分析服務可以在客戶資訊上下文中建立。

消費者支付和交易環境是為新的以客戶為中心的支付解決方案建立核心服務的場所。首先,客戶需要註冊新產品並設定其帳戶和產品偏好。為此,引入了以客戶為中心的支付管理服務。

對於非功能性原因(例如效能,安全性和可用性),我們將建立一個單獨的授權支付服務,稱為以客戶為中心的支付授權服務。最後,由於向客戶帳戶釋出交易可以晚於授權決定釋出,因此我們將建立與授權服務分離的交易釋出服務(Transaction Posting Service)。

對於產品子域,我們只會在每個有界的上下文中引用單個同名服務。例如,存款賬戶上下文只包含一個存款賬戶服務。整個服務系統現在看起來像這樣:

這個設計過程的最後一步是註釋將發生在服務之間的互動。事實上,人們可能想要模擬有界上下文之間的相互作用,以便梳理出單個服務,但為了覆蓋視覺效果,我們將最後描述這一步驟。在這個階段舉例說明所有可能的互動會造成視覺混淆,因此只會關注一些能夠幫助理解系統如何運作的關鍵資訊。這裡有些例子:

客戶使用網上銀行Web應用程式通過以客戶為中心的支付管理服務,註冊並設定新支付解決方案的偏好;
以客戶為中心的支付管理服務從客戶資訊服務中檢索客戶的產品組合;
客戶活動分析服務使用來自產品系統的資訊構建客戶財務狀況;
客戶通過移動銀行應用程式執行以客戶為中心的支付,該應用程式稱為以客戶為中心的支付授權服務;
以客戶為中心的支付授權服務,依次使用來自以客戶為中心的支付管理服務和客戶活動分析服務的資訊構建授權配置檔案;
一旦獲得授權,支付將被轉發至交易釋出服務完成,然後呼叫相應的產品服務;

關於微服務系統有幾點需要注意。首先,不要假定在為終端使用者活動提供服務時,這些互動中的每一個都會實時發生。例如,儘管以客戶為中心的授權服務需要來自其他一些服務的資訊,但可以使用基於事件的方法結合快取來確保其處理是獨立的,以便實時服務客戶的授權請求。

其次,可以在有界上下文之間建立防腐層(ACL),以提供鬆散的語義耦合。最後,雖然這是一個相當複雜的圖片,但沒有實現細節。換句話說,這種模式可以使用許多不同的技術來實現,包括語言,主機環境和網路協議。

最終的上下文對映(包括互動)如下所示:

最終,此係統設計過程的目的是,幫助企業如何在複雜解決方案中定義微服務的服務邊界進行最佳猜測。希望這裡的方法既能為服務建立一個良好的初始模型,又能更容易地重新繪製服務邊界。

Part 3:微服務設計畫布

微服務有自身的起源,通常從現有單體應用程式中湧現出來,以滿足眼前的需求。提高交付速度的願望推動了微服務的採用,開發人員通常採取“程式碼優先,問題排後”的方法,並重復實現有用的結果。這可行,但它是最佳的嗎?回答這個問題會帶來另一個問題:在開發微服務之前應該考慮哪些設計因素?正如軟體架構師Simon Brown所說,“前期做大設計是愚蠢的,但沒有前期的設計更愚蠢。”

借鑑精益畫布(lean canvas )方法設計商業模型,介紹一下微服務設計畫布。這個畫布是一個工具,可以幫助企業在構建服務之前捕獲服務中最重要的前端屬性。畫布採用了一種外部方法,它可以很好地將您的介面與其底層實現鬆散耦合。

你可以先在底部框中填寫服務的自由格式“說明”。從這裡開始,你應該完成“消費者任務”框,記錄服務消費者需要執行的任務。列舉服務的消費者以及他們需要執行的任務有助於明確服務的目的,並提供設計介面所需的材料輸入。這些資訊可以幫助填寫“介面”框。在這裡,消費者任務可以細分為與服務介面的特定互動。根據模式(查詢,命令,事件)對互動進行分類,將有助於形成底層服務實現,並最終推動API的設計。

除了服務的任務和互動之外,還必須考慮服務的非功能方面。可以使用“質量(Qualities)”框來確定服務屬性,例如可用性和效能級別,可擴充套件性方法和安全性期望。這將有助於消費者進一步瞭解服務,並影響其實施。總而言之,消費者的任務,介面和品質定義了服務的“表面”。這對系統的設計至關重要,因為它捕獲了系統中其他利益相關者所需的最重要的資訊。

在表面之下,還有一些關鍵的考慮因素。 “邏輯/規則”和“資料”框為服務設計人員提供了一個位置,以記錄這些領域的關鍵因素。抵制在這個階段太深的誘惑。沒有必要為服務的工作編寫一個完整的內部系統設計,但是可能需要感覺獨特和支援表面屬性所需的專案。最後,應列出服務“依賴關係”,以便調出服務需要的任務。對於具有相當數量業務邏輯的任務繁重的微服務,需要與更多面向資料的服務進行互動是很自然的。但是,本著微服務架構的精神,目標是最大限度地減少這些依賴關係。

來看幾個示例畫布。首先是以客戶為中心的支付管理服務畫布:

請注意,該服務看起來好像在互動中很直接,並且與其資料相對獨立。 從非功能角度來看,這不是關鍵任務,也不需要最高級別的事務完整性。 因此,它的實現可能相當簡單。

接下來是以客戶為中心的支付授權服務的畫布:

這項服務有一些更復雜的考慮因素。首先,它預計將是高容量和低延遲。這對服務的工程設計產生了明確的影響,需要複雜的授權資訊快取。其次,由於它的互動涉及金錢的流動,交易完整性和審計至關重要。最後,有一些事件互動意味著介面將超越典型的RESTful API。事實上,看到這些非功能性差異就清楚地說明,為什麼將以客戶為中心的支付解決方案的授權和管理功能,分解為單獨的服務是一個很好的設計決策。在系統檢視和服務檢視之間迭代將有助於定義服務邊界。

希望這個微服務設計畫布可以成為著手微服務部署的企業的有用工具。它清楚地與API設計聯絡在一起。

作者:Matt McLarty

原文連結:

1、Visualizing Microservices: API Design and Strategy

https://dzone.com/articles/visualizing-microservices-api-design-and-strategy

2、Visualizing Microservices: Designing a Microservice System

https://dzone.com/articles/visualizing-microservices-designing-a-microservice

3、Visualizing Microservices: The Microservice Design Canvas

https://dzone.com/articles/visualizing-microservices-the-microservice-design