电竞比分网-中国电竞赛事及体育赛事平台

分享

微服務(wù)設(shè)計模式

 代碼小伙兒 2021-02-16

https://www./blog-QEFWfPcRJ6.htm

微服務(wù)架構(gòu)已經(jīng)成為現(xiàn)代應(yīng)用程序開發(fā)的主流。雖然說它能夠解決某些問題,但卻也不是萬金油。而我們在使用這個體系架構(gòu)時,還有許多的問題要我們解決。這就需要學(xué)習(xí)這些問題的通用模式,并通過可復(fù)用的解決方案來解決問題。因此,有必要討論微服務(wù)的設(shè)計模式。但是在深入研究設(shè)計模式之前,我們還需了解微服務(wù)架構(gòu)的構(gòu)建原理:

  1. 可拓展性

  2. 可用性

  3. 彈性

  4. 獨立自主

  5. 分散治理

  6. 故障隔離

  7. 自動配置

  8. 通過DevOps持續(xù)交付


應(yīng)用這些構(gòu)建原理會帶來一些挑戰(zhàn)和問題。讓我們討論這些問題及其解決方案。
分解模式
按業(yè)務(wù)能力分解

問題:

微服務(wù)就是讓應(yīng)用服務(wù)松散耦合,但是將應(yīng)用程序分解成較小的部分還必須要在邏輯上實現(xiàn)。那我們?nèi)绾螌?yīng)用程序分解為小型服務(wù)呢?

解決方案:

一種策略就是按業(yè)務(wù)能力分解,業(yè)務(wù)能力是企業(yè)業(yè)務(wù)價值的體現(xiàn)。業(yè)務(wù)的功能取決于業(yè)務(wù)的類型。例如,保險公司的業(yè)務(wù)能力通常包括銷售,市場營銷,承保,理賠處理,開票,合規(guī)性等。每種業(yè)務(wù)能力都可以視為一種服務(wù),但它面向的是業(yè)務(wù)而不是技術(shù)。

按子域劃分

問題:

按業(yè)務(wù)功能來分解應(yīng)用程序或許是個不錯的思路。但是我們可能會遇到某些比較難以分解出來的類(God Classes),這種類在多種服務(wù)中通用。比如,訂單類用于“訂單管理”,“接單”,“訂單交付”等業(yè)務(wù)中。那我們該如何來分解呢?

解決方案:

對于這種難以分解出來的(God Classes)類,使用DDD(即領(lǐng)域驅(qū)動設(shè)計)可以解決。它使用子域和有界上下文概念來解決此問題。DDD將為企業(yè)創(chuàng)建的整個域模型分解為子域。每個子域都有一個模型,該模型的范圍稱為有界上下文。每個微服務(wù)將圍繞有界的上下文進(jìn)行開發(fā)。

注意:確定子域并不是件容易的事,這需要對業(yè)務(wù)有一定的了解。像業(yè)務(wù)功能一樣,通過分析業(yè)務(wù)及其組織結(jié)構(gòu)并確定不同的專業(yè)領(lǐng)域來標(biāo)識子域。

扼殺者模式

問題:

到目前為止,我們所討論的設(shè)計模式都是分解未開發(fā)的應(yīng)用程序,但是我們所做的工作中有80%是用于已開發(fā)的應(yīng)用程序(brownfield applications)中,這是個大型的整體應(yīng)用程序。上述所有設(shè)計模式并不是適用于它們,因為把它們作為一個整體應(yīng)用的同時將它們拆分成一個個較小的部分是一項艱巨的任務(wù)。

解決方案:

扼殺者模式可以解決此類問題。扼殺者模式是以纏繞類的藤蔓植物作為類比。該解決方案是與Web應(yīng)用程序配合使用,在Web應(yīng)用程序之間來回調(diào)用,對于每個URL的調(diào)用,一個服務(wù)可以分為不同的域并作為單獨的服務(wù)托管。這個想法是一次做一個域,這將會創(chuàng)建兩個單獨的應(yīng)用程序,它們并行存在于同一個URL空間中。最終,新重構(gòu)的應(yīng)用程序會“扼殺”或者替換原來的應(yīng)用程序,直到最后可以停止整個應(yīng)用程序。
整合模式
API網(wǎng)關(guān)模式

問題:

當(dāng)一個應(yīng)用程序被分解為多個微服務(wù)時,還有一些問題需要解決:

  1. 如何調(diào)用多個微服務(wù)來抽象化生產(chǎn)者信息。

  2. 在不同設(shè)備上(比如臺式機(jī),移動設(shè)備和平板電腦),由于UI可能存在不同,應(yīng)用程序需要不同的數(shù)據(jù)來響應(yīng)相同的后端服務(wù)。

  3. 不同的使用者對于可重復(fù)使用的微服務(wù)響應(yīng)格式可能不同,那由誰來進(jìn)行數(shù)據(jù)轉(zhuǎn)換或者字段操作。

  4. 生產(chǎn)者微服務(wù)可能不支持某些類型協(xié)議的處理方式。


解決方案:

API網(wǎng)關(guān)有助于解決因微服務(wù)實現(xiàn)而引起的許多問題,而不僅限于上述問題。

  1. API網(wǎng)關(guān)是任務(wù)微服務(wù)調(diào)用的單一入口點。

  2. 用作代理服務(wù),將請求路由至相關(guān)的微服務(wù),從而抽象出生產(chǎn)者的詳細(xì)信息。

  3. 將一個請求發(fā)送至多個服務(wù),然后把響應(yīng)結(jié)果聚合后發(fā)送回消費者。

  4. 通用的API網(wǎng)關(guān)無法滿足所有的消費者需求??梢詾槊糠N特定類型的客戶端創(chuàng)建細(xì)粒度的API。

  5. 將協(xié)議請求(例如AMQP)轉(zhuǎn)換成另外一個協(xié)議(例如HTTP),反之亦然,以便生產(chǎn)者和消費者處理它。

  6. 它還可以減輕微服務(wù)的身份驗證/授權(quán)責(zé)任。


聚合模式

問題:

我們已經(jīng)討論過如何解決API網(wǎng)關(guān)模式中的聚合數(shù)據(jù)問題。但是,接下來我們將會更加全面地討論它。比如,在將業(yè)務(wù)功能分解為幾個較小的邏輯代碼時,有必要考慮聚合每個服務(wù)返回的數(shù)據(jù)。這個任務(wù)不能留給消費者,因為如果這么做消費者可能需要了解生產(chǎn)者應(yīng)用程序的內(nèi)部實現(xiàn)。

解決方案:

聚合模式有助于解決此類問題。它討論了關(guān)于如何聚合來自不同服務(wù)的數(shù)據(jù),然后將最終響應(yīng)結(jié)果發(fā)送給消費者。我們可以通過以下兩種方式來實現(xiàn):

  1. 復(fù)合微服務(wù)將調(diào)用所有必需的微服務(wù),整合數(shù)據(jù),并在回退數(shù)據(jù)之前轉(zhuǎn)換數(shù)據(jù)。

  2. 用API網(wǎng)關(guān)將請求劃分為多個微服務(wù)并聚合數(shù)據(jù),然后再將其發(fā)送給使用者。

如果要應(yīng)用任何業(yè)務(wù)邏輯,建議選擇使用復(fù)合微服務(wù)。否則,API網(wǎng)關(guān)是已建立的解決方案。


客戶端UI組合模式

問題:

當(dāng)通過分解業(yè)務(wù)功能/子域來開發(fā)服務(wù)時,負(fù)責(zé)用戶體驗的服務(wù)必須從多個微服務(wù)中提取數(shù)據(jù)。在整體應(yīng)用中,從UI到后端服務(wù)只有一次調(diào)用,以檢索所有數(shù)據(jù)并刷新/提交UI頁面。但是,現(xiàn)在情況不一樣了。我們需要了解如何去做。

解決方案:

對于微服務(wù),必須將UI設(shè)計為具有屏幕/頁面的多個部分/區(qū)域的框架。每個部分都調(diào)用單個后端微服務(wù)以提取數(shù)據(jù),這稱為組合特定服務(wù)的UI組件。比如AngularJS和ReactJS之類的框架可以輕松地做到這一點。這些屏幕稱為單頁應(yīng)用程序(SPA)。這使應(yīng)用程序可以刷新屏幕的特定區(qū)域而不是刷新整個頁面。
數(shù)據(jù)庫模式
每個服務(wù)一個數(shù)據(jù)庫

問題:

如何來定義微服務(wù)的數(shù)據(jù)庫體系結(jié)構(gòu)?讓我們來看下需要解決的那些問題:

  1. 服務(wù)必須松耦合。它們可以獨立開發(fā),部署和擴(kuò)展。

  2. 業(yè)務(wù)事務(wù)可能會強(qiáng)制跨越多個服務(wù)的不變量。

  3. 一些業(yè)務(wù)事務(wù)需要查詢多個服務(wù)中的數(shù)據(jù)。

  4. 為了進(jìn)行擴(kuò)展有時必須對數(shù)據(jù)庫進(jìn)行復(fù)制和分片。

  5. 不同服務(wù)具有不同的數(shù)據(jù)存儲要求。


解決方案:

為了解決上述問題,必須為每個微服務(wù)設(shè)計一個數(shù)據(jù)庫。它必須僅對該服務(wù)專用,只能由微服務(wù)API訪問它,其他服務(wù)無法訪問。例如,對于關(guān)系型數(shù)據(jù)庫,我們可以使用每個服務(wù)一個專用的表,每個服務(wù)一個schema或每個服務(wù)一個數(shù)據(jù)庫服務(wù)器。每個微服務(wù)應(yīng)具有一個單獨的數(shù)據(jù)庫ID,這樣就可以提供單獨的訪問來設(shè)置一個隔離,防止它使用其他服務(wù)的表。

每個服務(wù)共享數(shù)據(jù)庫

問題:

我們已經(jīng)討論了每個服務(wù)一個數(shù)據(jù)庫是微服務(wù)的理想選擇,這在應(yīng)用程序開發(fā)前并且要使用DDD開發(fā)時,是可能實現(xiàn)的。但是,如果應(yīng)用程序是一個整體并且試圖闖入微服務(wù)時,那么非規(guī)范化就不是那么容易了。在這種情況下合適的架構(gòu)是什么呢?

解決方案:

每個服務(wù)共享數(shù)據(jù)庫不是理想的選擇,但卻是上述情況的可行解決方案。大多數(shù)人認(rèn)為這是微服務(wù)的反模式,但這對于棕地應(yīng)用程序來說,是將應(yīng)用程序分解成較小邏輯部分的一個很好的開始。這不適合綠地應(yīng)用程序。在這種模式下,一個數(shù)據(jù)庫可以與一個以上的微服務(wù)對齊,當(dāng)然也不是無限制的,最多限制為2-3個微服務(wù),否則擴(kuò)展性,自主性和獨立性將難以執(zhí)行。

命令查詢職責(zé)隔離(CQRS)

問題:

一旦我們實現(xiàn)了每個服務(wù)的數(shù)據(jù)庫,就肯定會有查詢,而且這需要來自多個服務(wù)的聯(lián)合數(shù)據(jù)——這是不可能的。那我們應(yīng)該如何在微服務(wù)架構(gòu)中實現(xiàn)查詢呢?

解決方案:

CQRS建議將應(yīng)用程序分為兩部分——命令端和查詢端。命令端負(fù)責(zé)處理創(chuàng)建,更新和刪除請求。查詢端負(fù)責(zé)通過使用實例化視圖來處理查詢的部分。通常將事件源模式與CQRS一起使用來為任何數(shù)據(jù)更改創(chuàng)建事件。通過訂閱事件流,可以使實例化視圖保持更新。

Saga模式

問題:

當(dāng)每個服務(wù)都有自己的數(shù)據(jù)庫并且一個業(yè)務(wù)事物跨越多個服務(wù)時,我們該如何確保各個服務(wù)之間的數(shù)據(jù)一致性呢?例如,對于客戶有信用額度的電子商務(wù)應(yīng)用程序,該應(yīng)用程序必須確保新訂單不會超過客戶的信用額度。由于訂單和客戶位于不用的數(shù)據(jù)庫中,因此應(yīng)用程序不能簡單地使用本地ACID事務(wù)。

解決方案:

Saga相當(dāng)于由幾個子請求組成的高級業(yè)務(wù)流程,每個子請求在單個服務(wù)中更新數(shù)據(jù)。每個請求都會有一個補(bǔ)償請求,該請求在請求失敗時執(zhí)行。它通過兩種方式實現(xiàn):

  1. 編排(Choreography):當(dāng)沒有總協(xié)調(diào)時,每個服務(wù)都會生成和監(jiān)聽另一個服務(wù)時間,并決定是否應(yīng)該采取行動。

  2. 編排器(Orchestration):負(fù)責(zé)一個Saga的決策和業(yè)務(wù)邏輯排序

觀測模式
日志匯總

問題:

一個應(yīng)用程序由在多臺服務(wù)器上運行的多個服務(wù)實例組成,請求通常跨越多個服務(wù)實例。每個服務(wù)實例均以標(biāo)準(zhǔn)化格式生成日志文件。我們該如何通過日志了解特定請求的應(yīng)用程序行為呢?

解決方案:

我們需要一個集中式日志記錄服務(wù),該服務(wù)可以匯總每個服務(wù)實例的日志。用戶可以搜索和分析日志。他們可以配置某些消息出現(xiàn)在日志中時觸發(fā)警報。例如,PCF(Pivotal Cloud Foundy)確實具有Loggeregator,它從PCF平臺的每個組件(路由器、控制器、diego等)以及應(yīng)用程序中收集日志。AWS Cloud Watch也做了同樣的事情。

性能指標(biāo)

問題:

當(dāng)使用微服務(wù)架構(gòu)而導(dǎo)致的服務(wù)組合增加時,對事務(wù)進(jìn)行監(jiān)控就變得非常重要,以便在出現(xiàn)問題時可以監(jiān)視模式并發(fā)送告警。我們應(yīng)該如何收集指標(biāo)來監(jiān)控應(yīng)用程序性能呢?

解決方案:

需要一個度量服務(wù)來收集關(guān)于單個操作的統(tǒng)計信息。它應(yīng)該聚合提供報告和告警的應(yīng)用程序服務(wù)的指標(biāo)。聚合度量有兩種模型:

  1. 推送:服務(wù)將指標(biāo)推送到指標(biāo)服務(wù),例如NewRelic,AppDynamics

  2. 提?。褐笜?biāo)服務(wù)從服務(wù)中提取指標(biāo),例如Prometheus


分布式跟蹤

問題:

在微服務(wù)架構(gòu)中,請求通??缭蕉鄠€服務(wù)。每個服務(wù)通過跨多個服務(wù)執(zhí)行一個或多個操作來處理請求。那么,我們?nèi)绾胃櫠说蕉苏埱髞斫鉀Q問題呢?

解決方案:

我們需要一項服務(wù):

  1. 為每個外部請求分配一個唯一的外部請求ID

  2. 將外部請求ID傳遞給所有服務(wù)

  3. 在所有的日志消息中包含外部請求ID

  4. 記錄有關(guān)請求和在集中服務(wù)中處理外部請求時執(zhí)行的請求和操作的信息(例如,開始時間、結(jié)束時間)


Spring Cloud Slueth以及Zipkin server都是通用實現(xiàn)。

健康檢查

問題:

當(dāng)實施了微服務(wù)架構(gòu)時,服務(wù)可能會啟動,但無法處理事務(wù)。在這種情況下,如何確保請求不會轉(zhuǎn)到那些失敗的實例呢?使用負(fù)載均衡模式實現(xiàn)。

解決方案:

每個服務(wù)都需要有一個端點,可以用來檢查應(yīng)用程序的健康度,比如/health。這個API應(yīng)該檢查主機(jī)的狀態(tài)、與其他服務(wù)/基礎(chǔ)設(shè)施的連接以及任何特定的邏輯。

Spring Boot Actuator確實實現(xiàn)了一個/health端點,并且該實現(xiàn)也可以自定義。
橫切關(guān)注模式
外部配置

問題:

服務(wù)通常也會調(diào)用其他服務(wù)和數(shù)據(jù)庫。對于開發(fā)、QA、UAT、prod等每個環(huán)境,端點URL或某些配置屬性可能不同。任何這些屬性的更改都可能需要重新構(gòu)建和重新部署服務(wù)。如何避免對配置更改進(jìn)行代碼修改呢?

解決方案:

外部化所有配置,包括端點url和憑證。應(yīng)用程序應(yīng)該在啟動或運行時加載它們。

Spring Cloud config server提供了將屬性外部化到GitHub并將其作為環(huán)境屬性加載的選項。應(yīng)用程序可以在啟動時訪問它們,也可以在不重啟服務(wù)器的情況下刷新它們。

服務(wù)發(fā)現(xiàn)模式

問題:

當(dāng)微服務(wù)出現(xiàn)的時候,我們需要解決一些關(guān)于調(diào)用服務(wù)的問題:

  1. 使用容器技術(shù),IP地址被動態(tài)分配給服務(wù)實例。每次地址更改時,使用者服務(wù)可能會中斷,并需要手動更改。

  2. 每個服務(wù)的URL都必須被使用者記住并成為緊密耦合的。


那么消費者或者路由器如何知道所有可用的服務(wù)實例和位置呢?

解決方案:

我們需要創(chuàng)建一個服務(wù)注冊中心,用來保存每個生產(chǎn)者服務(wù)的元數(shù)據(jù)。服務(wù)實例在啟動時注冊到注冊中心,在關(guān)閉時注銷注冊。消費者或路由器查詢注冊表并找出服務(wù)的位置。注冊中心還需要對生產(chǎn)者服務(wù)進(jìn)行健康檢查,來確保只有服務(wù)的工作實例可以通過它使用。有兩種類型的服務(wù)發(fā)現(xiàn):客戶端和服務(wù)器端。客戶端發(fā)現(xiàn)的一個例子是Netflix Eureka,服務(wù)器端發(fā)現(xiàn)的一個例子是AWS ALB。

斷路器模式

問題:

服務(wù)通常會調(diào)用其他服務(wù)來檢索數(shù)據(jù),下游服務(wù)可能會出現(xiàn)故障。這樣做有兩個問題:首先,請求將繼續(xù)使用服務(wù)中斷狀態(tài),耗盡網(wǎng)絡(luò)資源并降低性能。其次,用戶體驗將是糟糕的和不可預(yù)測的。如何避免級聯(lián)服務(wù)故障并優(yōu)雅地處理故障呢?

解決方案:

消費者應(yīng)該通過代理調(diào)用遠(yuǎn)程服務(wù),代理的行為類似于斷路器。當(dāng)連續(xù)故障數(shù)超過閾值時,斷路器跳閘,在超時期間,所有調(diào)用遠(yuǎn)程服務(wù)的嘗試都會立即失敗。超時過期后,斷路器允許有限數(shù)量的測試請求通過。如果這些請求成功,斷路器將恢復(fù)正常工作。否則,如果出現(xiàn)故障,超時周期將再次開始。

Netflix Hystrix是斷路器模式的良好實現(xiàn)。它還可以幫助你定義一個備用機(jī)制,可以使用斷路器跳閘。這提供了更好的用戶體驗。

藍(lán)綠部署模式

問題:

使用微服務(wù)架構(gòu)時,一個應(yīng)用程序可以有許多微服務(wù)。假如我們停止所有服務(wù),然后部署一個增強(qiáng)版本,停機(jī)時間將是巨大的,并可能會影響到業(yè)務(wù)。此外,回滾將是一場噩夢。我們?nèi)绾伪苊饣驕p少部署期間服務(wù)的停機(jī)時間呢?  

解決方案:

可以使用藍(lán)綠部署策略來減少或消除停機(jī)時間。它通過運行兩個相同的生產(chǎn)環(huán)境(藍(lán)色和綠色)來實現(xiàn)這一點。讓我們假設(shè)綠色是現(xiàn)有的活動實例,藍(lán)色是應(yīng)用程序的新版本。在任何時候,只有一個環(huán)境是運行狀態(tài), 該環(huán)境服務(wù)于所有生產(chǎn)流量。所有云平臺都提供了實現(xiàn)藍(lán)綠部署的選項。

與微服務(wù)架構(gòu)一起使用的還有許多其他模式,比如Sidecar、鏈?zhǔn)轿⒎?wù)、分支微服務(wù)、事件源模式、持續(xù)交付模式等等。隨著我們在微服務(wù)方面獲得更多的經(jīng)驗,這個名單還在不斷增長。我現(xiàn)在停下來聽聽你正在使用的微服務(wù)模式。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多