《微服務(wù)架構(gòu)設(shè)計(jì)模式》讀書(shū)筆記---第二章:微服務(wù)拆分策略

架構(gòu)是什么

首先看下軟件架構(gòu)的含義。

計(jì)算機(jī)系統(tǒng)的軟件架構(gòu)是構(gòu)建這個(gè)系統(tǒng)所需要的一組結(jié)構(gòu),包括軟件元素、它們之間的關(guān)系以及兩者的屬性。
—Bass等著《Documenting Software Architectures: Views and Beyond》

其實(shí)質(zhì)是應(yīng)用程序的架構(gòu)是將軟件分解為元素(element)和這些元素之間的關(guān)系(relation)。

怎么了解一個(gè)架構(gòu)

從更具體的角度而言,應(yīng)用程序的架構(gòu)可以從多個(gè)視角來(lái)看。Phillip Krutchen在他經(jīng)典的論文《Architectural Blueprints —The 4+1 View Model of Software Architecture》中提出了軟件架構(gòu)的4+1視圖。

image.png
  • 邏輯視圖:開(kāi)發(fā)人員創(chuàng)建的軟件元素。在面向?qū)ο蟮恼Z(yǔ)言中,這些元素是類(lèi)和包。它們之間的關(guān)系是類(lèi)和包之間的關(guān)系,包括繼承、關(guān)聯(lián)和依賴(lài)。
  • 實(shí)現(xiàn)視圖:構(gòu)建編譯系統(tǒng)的輸出。此視圖由表示打包代碼的模塊和組件組成,組件是由一個(gè)或多個(gè)模塊組成的可執(zhí)行或可部署單元。在Java中,模塊是JAR文件,組件通常是WAR文件或可執(zhí)行JAR文件。它們之間的關(guān)系包括模塊之間的依賴(lài)關(guān)系以及組件和模塊之間的組合關(guān)系。
  • 進(jìn)程視圖:運(yùn)行時(shí)的組件。每個(gè)元素都是一個(gè)進(jìn)程,進(jìn)程之間的關(guān)系代表進(jìn)程間通信。
  • 部署視圖:進(jìn)程如何映射到機(jī)器。此視圖中的元素由(物理或虛擬)計(jì)算機(jī)和進(jìn)程組成。機(jī)器之間的關(guān)系代表網(wǎng)絡(luò)。該視圖還描述了進(jìn)程和機(jī)器之間的關(guān)系。

4+1中的+1是指場(chǎng)景,它負(fù)責(zé)把視圖串聯(lián)在一起。

每一個(gè)視圖都描述了架構(gòu)的一個(gè)重要側(cè)面。場(chǎng)景把視圖中的元素如何協(xié)作串聯(lián)在一起。

為什么架構(gòu)重要?

應(yīng)用程序有兩個(gè)層面的需求。功能性需求和非功能性需求。
第一類(lèi)是功能性需求,這些需求決定一個(gè)應(yīng)用程序做什么。這些通常都包含在用例(use case)或者用戶(hù)故事(user story)中。應(yīng)用的架構(gòu)其實(shí)跟這些功能性需求沒(méi)什么關(guān)系。功能性需求可以通過(guò)任意的架構(gòu)來(lái)實(shí)現(xiàn),甚至是非常糟糕的大泥球架構(gòu)。
架構(gòu)的重要性在于,它幫助應(yīng)用程序滿(mǎn)足了第二類(lèi)需求:非功能性需求。我們把這類(lèi)需求也稱(chēng)之為質(zhì)量屬性需求,或者簡(jiǎn)稱(chēng)為“能力”。這些非功能性需求決定一個(gè)應(yīng)用程序在運(yùn)行時(shí)的質(zhì)量,比如可擴(kuò)展性和可靠性。它們也決定了開(kāi)發(fā)階段的質(zhì)量,包括可維護(hù)性、可測(cè)試性、可擴(kuò)展性和可部署性。為應(yīng)用程序所選擇的架構(gòu)將決定這些質(zhì)量屬性。

什么是架構(gòu)的風(fēng)格

架構(gòu)風(fēng)格根據(jù)結(jié)構(gòu)組織模式定義了一系列此類(lèi)系統(tǒng)。
更具體地說(shuō),架構(gòu)風(fēng)格確定可以在該風(fēng)格的實(shí)例中使用的組件和連接器的詞匯表,以及關(guān)于如何組合它們的一組約束。
特定的架構(gòu)風(fēng)格提供了有限的元素(組件)和關(guān)系(連接器),你可以從中定義應(yīng)用程序架構(gòu)的視圖。

例如:分層式架構(gòu)風(fēng)格
分層架構(gòu)將軟件元素按“層”的方式組織。每個(gè)層都有明確定義的職責(zé)。分層架構(gòu)還限制了層之間的依賴(lài)關(guān)系。每一層只能依賴(lài)于緊鄰其下方的層(如果嚴(yán)格分層)或其下面的任何層。三層架構(gòu)是應(yīng)用于邏輯視圖的分層架構(gòu),可以分為表現(xiàn)層,業(yè)務(wù)邏輯層,數(shù)據(jù)持久化層。

六邊形架構(gòu)是分層架構(gòu)風(fēng)格的替代品。六邊形架構(gòu)風(fēng)格選擇以業(yè)務(wù)邏輯為中心的方式組織邏輯視圖。

image.png

應(yīng)用程序具有一個(gè)或多個(gè)入站適配器,而不是表示層,它通過(guò)調(diào)用業(yè)務(wù)邏輯來(lái)處理來(lái)自外部的請(qǐng)求。

分層架構(gòu)和六邊形架構(gòu)都是架構(gòu)風(fēng)格的實(shí)例。

微服務(wù)架構(gòu)是一種架構(gòu)風(fēng)格

單體架構(gòu):將應(yīng)用程序構(gòu)建為單個(gè)可執(zhí)行和可部署組件。
微服務(wù)架構(gòu):將應(yīng)用程序構(gòu)建為松耦合、可獨(dú)立部署的一組服務(wù)。

服務(wù)是一個(gè)單一的、可獨(dú)立部署的軟件組件,它實(shí)現(xiàn)了一些有用的功能。微服務(wù)架構(gòu)中的每項(xiàng)服務(wù)都有自己的架構(gòu),可能還有獨(dú)特的技術(shù)棧。但是典型的服務(wù)往往都具有六邊形架構(gòu)。

image.png

微服務(wù)架構(gòu)的松耦合
微服務(wù)架構(gòu)的最核心特性是服務(wù)之間的松耦合性 。
服務(wù)之間的交互采用API完成,以此

  • 封裝了服務(wù)的實(shí)現(xiàn)細(xì)節(jié)
  • 可以在不影響客戶(hù)端的情況下,對(duì)實(shí)現(xiàn)方式做出修改。

共享類(lèi)庫(kù)的角色
最簡(jiǎn)單的方式是,在微服務(wù)架構(gòu)中使用共享庫(kù)。如此,似乎是減少服務(wù)中代碼重復(fù)的好方法。但是可能,會(huì)意外地在服務(wù)之間引入耦合。
應(yīng)該努力使用共享庫(kù)來(lái)實(shí)現(xiàn)不太可能改變的功能。例如,在典型的應(yīng)用程序中,在每個(gè)服務(wù)中都實(shí)現(xiàn)一個(gè)通用的Money類(lèi)(例如用來(lái)實(shí)現(xiàn)幣種轉(zhuǎn)換等固定功能)沒(méi)有任何意義。相反,你應(yīng)該創(chuàng)建一個(gè)供所有服務(wù)使用的共享庫(kù)。

服務(wù)的大小并不重要
實(shí)際上,服務(wù)大小不是一個(gè)重要的考慮因素。
更好的目標(biāo)是將精心設(shè)計(jì)的服務(wù)定義為能夠由小團(tuán)隊(duì)開(kāi)發(fā)的服務(wù),并且交付時(shí)間最短,與其他團(tuán)隊(duì)協(xié)作最少。

如何定義微服務(wù)架構(gòu)

image.png

第一步是將應(yīng)用程序的需求提煉為各種關(guān)鍵請(qǐng)求。不是根據(jù)特定的進(jìn)程間通信技術(shù)(如REST或消息)來(lái)描述這些請(qǐng)求,而是使用系統(tǒng)操作這個(gè)概念。系統(tǒng)操作(system operation)是應(yīng)用程序必須處理的請(qǐng)求的一種抽象描述。它既可以是更新數(shù)據(jù)的命令,也可以是檢索數(shù)據(jù)的查詢(xún)。

第二步是確定如何分解服務(wù)。有幾種策略可供選擇。

  • 一種源于業(yè)務(wù)架構(gòu)學(xué)派的策略是定義與業(yè)務(wù)能力相對(duì)應(yīng)的服務(wù)。
  • 另一種策略是圍繞領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的子域來(lái)分解和設(shè)計(jì)服務(wù)。
    但這些策略的最終結(jié)果都是圍繞業(yè)務(wù)概念而非技術(shù)概念分解和設(shè)計(jì)的服務(wù)。

第三步是確定每個(gè)服務(wù)的API。為此,你將第一步中標(biāo)識(shí)的每個(gè)系統(tǒng)操作分配給服務(wù)。服務(wù)可以完全獨(dú)立地實(shí)現(xiàn)操作。或者,它可能需要與其他服務(wù)協(xié)作。

識(shí)別系統(tǒng)操作

起點(diǎn)是應(yīng)用程序的需求,包括用戶(hù)故事及其相關(guān)的用戶(hù)場(chǎng)景。

image.png

第一步,創(chuàng)建由關(guān)鍵類(lèi)組成的抽象領(lǐng)域模型,這些關(guān)鍵類(lèi)提供用于描述系統(tǒng)操作的詞匯表??梢允褂妹麨槭录L(fēng)暴(Event Storming)的技術(shù)定義領(lǐng)域模型。
創(chuàng)建領(lǐng)域模型會(huì)采用一些標(biāo)準(zhǔn)的技術(shù),例如通過(guò)與領(lǐng)域?qū)<覝贤ê螅治鲇脩?hù)故事和場(chǎng)景中頻繁出現(xiàn)的名詞。

第二步,確定系統(tǒng)操作,并根據(jù)領(lǐng)域模型描述每個(gè)系統(tǒng)操作的行為。系統(tǒng)操作可以創(chuàng)建、更新或刪除領(lǐng)域?qū)ο?,以及?chuàng)建或破壞它們之間的關(guān)系。

可以把系統(tǒng)操作分為兩種類(lèi)型:
命令型:創(chuàng)建、更新或刪除數(shù)據(jù)的系統(tǒng)操作。
查詢(xún)型:查詢(xún)和讀取數(shù)據(jù)的系統(tǒng)操作。

不必在意這些實(shí)現(xiàn)細(xì)節(jié),識(shí)別系統(tǒng)指令的切入點(diǎn)是分析用戶(hù)故事和場(chǎng)景中的動(dòng)詞。多數(shù)與系統(tǒng)操作是命令。查詢(xún)雖然僅僅是簡(jiǎn)單地獲取數(shù)據(jù),但是也同樣重要。

抽象的領(lǐng)域模型和系統(tǒng)操作能夠回答這個(gè)應(yīng)用“做什么”這一問(wèn)題。

根據(jù)業(yè)務(wù)能力進(jìn)行服務(wù)拆分

有多種拆分策略可供識(shí)別應(yīng)用服務(wù)。但是殊途同歸,這些策略的結(jié)果都是一樣的:一個(gè)包含若干服務(wù)的架構(gòu),這樣的架構(gòu)是以業(yè)務(wù)而不是技術(shù)概念為中心。
我們先來(lái)看看第一個(gè)策略:使用業(yè)務(wù)能力來(lái)定義服務(wù)。

業(yè)務(wù)能力是指一些能夠?yàn)楣荆ɑ蚪M織)產(chǎn)生價(jià)值的商業(yè)活動(dòng)。特定業(yè)務(wù)的業(yè)務(wù)能力取決于這個(gè)業(yè)務(wù)的類(lèi)型。例如,保險(xiǎn)公司業(yè)務(wù)能力通常包括承保、理賠管理、賬務(wù)和合規(guī)等。

組織的業(yè)務(wù)能力通常是指這個(gè)組織的業(yè)務(wù)是做什么,它們通常都是穩(wěn)定的。與之相反,組織采用何種方式來(lái)實(shí)現(xiàn)它的業(yè)務(wù)能力,是隨著時(shí)間不斷變化的。

一個(gè)組織有哪些業(yè)務(wù)能力,是通過(guò)對(duì)組織的目標(biāo)、結(jié)構(gòu)和商業(yè)流程的分析得來(lái)的。每一個(gè)業(yè)務(wù)能力都可以被認(rèn)為是一個(gè)服務(wù)。業(yè)務(wù)能力規(guī)范包含多項(xiàng)元素,比如輸入和輸出、服務(wù)等級(jí)協(xié)議(SLA)。

業(yè)務(wù)能力通常集中在特定的業(yè)務(wù)對(duì)象上。例如,理賠業(yè)務(wù)對(duì)象是理賠管理功能的重點(diǎn)。能力通??梢苑纸鉃樽幽芰?。例如,理賠管理能力具有多個(gè)子能力,包括理賠信息管理、理賠審核和理賠付款管理。

image.png

從業(yè)務(wù)能力到服務(wù)
某些頂級(jí)能力(如會(huì)計(jì)記賬能力)將映射到服務(wù)。在其他情況下,子能力映射到服務(wù)。決定將哪個(gè)級(jí)別的能力層次結(jié)構(gòu)映射到服務(wù)是一個(gè)非常主觀的判斷。

image.png

圍繞能力組織服務(wù)的一個(gè)關(guān)鍵好處是,因?yàn)樗鼈兪欠€(wěn)定的,所以最終的架構(gòu)也將相對(duì)穩(wěn)定。

根據(jù)子域進(jìn)行服務(wù)拆分

領(lǐng)域模型以解決具體問(wèn)題的方式包含了一個(gè)領(lǐng)域內(nèi)的知識(shí)。它定義了當(dāng)前領(lǐng)域相關(guān)團(tuán)隊(duì)的詞匯表,DDD也稱(chēng)之為通用語(yǔ)言(Ubiquitous language)。

在微服務(wù)架構(gòu)的設(shè)計(jì)層面,DDD有兩個(gè)特別重要的概念,子域和限界上下文。

識(shí)別子域的方式跟識(shí)別業(yè)務(wù)能力一樣:分析業(yè)務(wù)并識(shí)別業(yè)務(wù)的不同專(zhuān)業(yè)領(lǐng)域,分析產(chǎn)出的子域定義結(jié)果也會(huì)跟業(yè)務(wù)能力非常接近。

image.png

拆分單體應(yīng)用為服務(wù)的難點(diǎn)

  • 網(wǎng)絡(luò)延遲。
  • 同步進(jìn)程間通信導(dǎo)致可用性降低。
  • 在服務(wù)之間維持?jǐn)?shù)據(jù)一致性。
  • 獲取一致的數(shù)據(jù)視圖。
  • 上帝類(lèi)阻礙了拆分,更好的方法是應(yīng)用DDD并將每個(gè)服務(wù)視為具有自己的領(lǐng)域模型的單獨(dú)子域。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容