微服务的设计模式,你用了几个
目錄
1. 分解模式
a. 按業(yè)務(wù)能力分解
b. 按子域分解
c. 扼殺者模式
2. 集成模式
a. API 網(wǎng)關(guān)模式
b. 聚合器模式
c. 客戶端組合模式
3. 數(shù)據(jù)庫模式
a. 每個服務(wù)的數(shù)據(jù)庫
b. 共享數(shù)據(jù)庫
c. 命令查詢職責(zé)分離 (CQRS)
d. Saga模式
4. 可觀察性模式
a. 日志聚合
b. 性能指標(biāo)
c. 分布式追蹤
d. 健康檢查
5. 跨領(lǐng)域關(guān)注模式(Cross-Cutting Concern)
a. 外部配置
b. 服務(wù)發(fā)現(xiàn)模式
c. 斷路器模式
d. 藍(lán)綠部署模式
?微服務(wù)架構(gòu)已經(jīng)成為現(xiàn)代應(yīng)用開發(fā)的主流選擇。雖然它解決了某些問題,但它不是靈丹妙藥,也有幾個缺點(diǎn)。因此,我們需要討論微服務(wù)的設(shè)計模式,幫助我們解決一些問題。
在深入研究設(shè)計模式之前,我們需要了解微服務(wù)的構(gòu)建原則:
但是,應(yīng)用所有這些原則會帶來一些挑戰(zhàn)和問題。接下來,讓我們討論這些問題及其解決方案。
1. 分解模式
a. 按業(yè)務(wù)能力分解
問題
微服務(wù)的目標(biāo)之一是讓服務(wù)松散耦合,應(yīng)用單一職責(zé)原則。但是,將應(yīng)用程序分解成更小的部分必須符合邏輯。我們?nèi)绾螌?yīng)用程序分解為小服務(wù)?
解決方案
一種策略是按業(yè)務(wù)能力分解----業(yè)務(wù)能力是企業(yè)為了創(chuàng)造價值而做的事情,給定業(yè)務(wù)的能力集取決于業(yè)務(wù)類型。例如,保險公司的能力通常包括銷售、營銷、承保、理賠處理、計費(fèi)等。每個業(yè)務(wù)能力都可以被認(rèn)為是一種服務(wù)。
b. 按子域分解
問題
使用業(yè)務(wù)能力分解應(yīng)用程序可能是一個好的開始,但你會遇到所謂的“上帝類(God Classes)”,它并不容易分解。這些類將在多個服務(wù)中通用。例如,Order 類將用于訂單管理、接單、訂單交付等,我們?nèi)绾畏纸馑鼈?#xff1f;
備注:
”去除上帝類”是指把一個看似功能很強(qiáng)且很難維護(hù)的類,按照職責(zé)把自己的屬性或方法分派到各自的類中或分解成功能明確的類,從而去掉上帝類。
解決方案
對于“God Classes”問題,可以通過DDD(領(lǐng)域驅(qū)動設(shè)計)來拯救。它使用子域和有界上下文概念來解決這個問題。DDD 將為企業(yè)創(chuàng)建的整個域模型分解為子域,每個子域都有一個模型,該模型的范圍將稱為有界上下文。每個微服務(wù)都將圍繞有界上下文開發(fā)。
注意:識別子域并非易事。它需要對業(yè)務(wù)的了解。與業(yè)務(wù)能力一樣,子域是通過分析業(yè)務(wù)及其組織結(jié)構(gòu)并確定不同的專業(yè)領(lǐng)域來確定的。
c. 扼殺者模式
問題
到目前為止,我們討論的設(shè)計模式是分解綠地應(yīng)用程序(Greenfield),但我們所做的 80% 的工作是處理棕地應(yīng)用程序(Brownfield),它們是大型的單體應(yīng)用程序。將上述所有設(shè)計模式應(yīng)用于它們將很困難,因?yàn)榘阉鼈兎纸獬筛〉牟糠质且豁?xiàng)艱巨的任務(wù)。
備注:
綠地應(yīng)用程序(Greenfield)
即一個新項(xiàng)目,從頭開始一個新的軟件項(xiàng)目。類比是在綠地上施工,無需改造或拆除現(xiàn)有結(jié)構(gòu)。
(來自http://en.wikipedia.org/wiki/Greenfield_project)
棕地應(yīng)用程序(Brownfield)
Brownfield開發(fā)是IT行業(yè)中常用的術(shù)語,用于描述現(xiàn)有結(jié)構(gòu)首先需要拆除的網(wǎng)站,即在現(xiàn)有軟件項(xiàng)目中構(gòu)建。
(來自http://en.wikipedia.org/wiki/Brownfield_(software_development))
解決方案
這就需要扼殺者模式(Strangler)來拯救。
扼殺者模式是基于一個藤蔓扼殺它所纏繞的樹的類比。此解決方案適用于 Web 應(yīng)用程序,可以將服務(wù)分解為不同的域并作為單獨(dú)的服務(wù)托管。一次做一個域,這將創(chuàng)建兩個獨(dú)立的應(yīng)用程序,它們并排在同一個 URI 空間中。最終,新重構(gòu)的應(yīng)用程序“扼殺”或替換原始應(yīng)用程序,直到你最終可以放棄傳統(tǒng)的單體應(yīng)用程序。
[澳大利亞]地區(qū)的自然奇觀之一是巨大的扼殺者藤蔓。 他們在無花果樹的樹枝上播種,并逐漸沿著樹下工作,直到扎根在土壤中。 多年來,它們長成奇妙而美麗的形狀,同時勒死并殺死了作為寄主的樹。
2. 集成模式
a. API 網(wǎng)關(guān)模式
問題
當(dāng)應(yīng)用程序分解為較小的微服務(wù)時,需要解決一些問題:
解決方案
API 網(wǎng)關(guān)有助于解決微服務(wù)帶來的許多問題:
b. 聚合器模式
問題
我們已經(jīng)討論了解決 API 網(wǎng)關(guān)模式中的聚合數(shù)據(jù)問題。但是,我們將在這里全面討論它。當(dāng)將業(yè)務(wù)功能分解為幾個較小的代碼段時,有必要考慮如何聚合每個服務(wù)返回的數(shù)據(jù)。這個責(zé)任不能留給消費(fèi)者,因?yàn)樗赡苄枰私馍a(chǎn)者的內(nèi)部實(shí)現(xiàn)。
解決方案
聚合器模式有助于解決這個問題。它可以聚合來自不同服務(wù)的數(shù)據(jù),然后再發(fā)送給消費(fèi)者。這可以通過兩種方式完成:
如果還要處理業(yè)務(wù)邏輯,建議選擇復(fù)合微服務(wù)。
c. 客戶端組合模式
問題
當(dāng)通過分解業(yè)務(wù)能力/子域來開發(fā)服務(wù)時,客戶端必須從多個微服務(wù)中拉取數(shù)據(jù)。在單體世界中,客戶端一般只需要調(diào)用一次后端服務(wù)來查詢或刷新所有數(shù)據(jù)。然而,現(xiàn)在情況將不一樣了,我們需要了解如何去做。
解決方案
對于微服務(wù),客戶端可能需要設(shè)計為具有多個部分/區(qū)域的骨架。每個部分都會調(diào)用一個單獨(dú)的后端微服務(wù)來拉取數(shù)據(jù)。這稱為單頁應(yīng)用程序 (Single Page Applications,SPA),像 AngularJS 和 ReactJS 這樣的框架有助于輕松地做到這一點(diǎn)。在需要刷新時,應(yīng)用程序能夠刷特定區(qū)域而不是整個頁面。
3. 數(shù)據(jù)庫模式
a. 每個服務(wù)的數(shù)據(jù)庫
問題
如何定義微服務(wù)的數(shù)據(jù)庫架構(gòu)也是一個問題:
解決方案
為了解決上述問題,每個微服務(wù)必須設(shè)計一個數(shù)據(jù)庫,它必須僅供該服務(wù)專用。它也應(yīng)該只能通過微服務(wù) API 訪問,而不能被其他服務(wù)直接訪問。例如,對于關(guān)系數(shù)據(jù)庫,我們可以使用 private-tables-per-service、schema-per-service 或 database-server-per-service。每個微服務(wù)都應(yīng)該有一個單獨(dú)的數(shù)據(jù)庫 id,以便可以給予單獨(dú)的訪問權(quán)限,并防止它使用其他服務(wù)表。
備注:
Private-tables-per-service——每一服務(wù)擁有一系列只能被該服務(wù)訪問的表
Schema-per-service——每一服務(wù)擁有一個為該服務(wù)所私有的數(shù)據(jù)庫Schema
Database-server-per-service——每一服務(wù)擁有自己的數(shù)據(jù)庫
b. 共享數(shù)據(jù)庫
問題
每個服務(wù)一個數(shù)據(jù)庫是微服務(wù)的理想選擇。當(dāng)應(yīng)用程序是全新的并且要使用 DDD 開發(fā)時,這是可能的。但是,如果應(yīng)用程序是單體應(yīng)用程序并試圖改進(jìn)為微服務(wù)架構(gòu),那么就不是那么容易了。在這種情況下,合適的架構(gòu)是什么?
解決方案
共享數(shù)據(jù)庫并不理想,但這是上述場景的解決方案。大多數(shù)人認(rèn)為這是微服務(wù)的反模式,但對于棕地應(yīng)用程序,這是將應(yīng)用程序分解為更小部分的良好開端。在這種模式中,一個數(shù)據(jù)庫可以供多個微服務(wù)調(diào)用,但最多只能限制在 2-3 個,否則擴(kuò)展性、自治性和獨(dú)立性將難以執(zhí)行。
c. 命令查詢職責(zé)分離 (CQRS)
問題
一旦我們實(shí)現(xiàn)了每個服務(wù)的數(shù)據(jù)庫,就需要查詢。那么,對于來自多個服務(wù)的聯(lián)合數(shù)據(jù),我們?nèi)绾卧谖⒎?wù)架構(gòu)中實(shí)現(xiàn)查詢呢?
解決方案
CQRS 建議將應(yīng)用程序分成兩部分——命令端和查詢端。
CQRS 將系統(tǒng)中的操作分為兩類,即「命令」(Command) 與「查詢」(Query)。命令則是對會引起數(shù)據(jù)發(fā)生變化操作的總稱,即我們常說的新增,更新,刪除這些操作,都是命令。而查詢則和字面意思一樣,即不會對數(shù)據(jù)產(chǎn)生變化的操作,只是按照某些條件查找數(shù)據(jù)。
查詢端使用物化視圖處理查詢部分。視圖會被保存在訂閱了事件的服務(wù)中,每個服務(wù)在更新數(shù)據(jù)時會發(fā)布出這些事件。例如,網(wǎng)店可以通過維護(hù)一個客戶信息和訂單信息的Join視圖來查詢特定區(qū)域客戶和他們的近期訂單。該視圖由訂閱了客戶信息事件和訂單信息事件的服務(wù)進(jìn)行更新。
d. Saga模式
問題
當(dāng)每個服務(wù)都有自己的數(shù)據(jù)庫,一個請求事務(wù)跨越多個服務(wù)時,我們?nèi)绾伪WC跨服務(wù)的數(shù)據(jù)一致性呢?例如,對于電子商務(wù)應(yīng)用程序,應(yīng)用程序必須確保新訂單不會超過客戶的信用額度。由于 Orders 和 Customers 位于不同的數(shù)據(jù)庫中,因此應(yīng)用程序不能簡單地使用本地 ACID 事務(wù)。
解決方案
Saga 代表一個高級業(yè)務(wù)流程,它由多個子請求組成,每個子請求都更新單個服務(wù)中的數(shù)據(jù)。每個請求都有一個補(bǔ)償請求,在請求失敗時執(zhí)行。
它可以通過兩種方式實(shí)現(xiàn):
4. 可觀察性模式
a. 日志聚合
問題
考慮一個用例,其中應(yīng)用程序由在多臺機(jī)器上運(yùn)行的多個服務(wù)實(shí)例組成。請求通常跨越多個服務(wù)實(shí)例,每個服務(wù)實(shí)例都會生成一個標(biāo)準(zhǔn)化格式的日志文件,我們?nèi)绾瓮ㄟ^日志了解特定請求的應(yīng)用程序行為?
解決方案
我們需要一個集中的日志服務(wù)來聚合來自每個服務(wù)實(shí)例的日志。用戶可以搜索和分析日志,還可以在日志中配置出現(xiàn)某些消息時觸發(fā)的警報。例如,PCF 確實(shí)有 Loggeregator,它從 PCF 平臺的每個組件(路由器、控制器、diego 等)以及應(yīng)用程序收集日志。AWS Cloud Watch 也有同樣的作用。
b. 性能指標(biāo)
問題
當(dāng)服務(wù)數(shù)量不斷增加時,密切關(guān)注應(yīng)用性能變得至關(guān)重要,以便可以出現(xiàn)問題時發(fā)送警報。我們應(yīng)該如何收集指標(biāo)來監(jiān)控應(yīng)用程序性能?
解決方案
需要度量服務(wù)來收集有關(guān)單個操作的統(tǒng)計信息。有兩種聚合指標(biāo)的模型:
- Push — 服務(wù)將指標(biāo)推送到指標(biāo)服務(wù),例如 NewRelic、AppDynamics、Prometheus
- Pull — 指標(biāo)服務(wù)從服務(wù)中提取指標(biāo),例如 Prometheus
c. 分布式追蹤
問題
在微服務(wù)架構(gòu)中,請求通常跨越多個服務(wù)。那么,我們?nèi)绾胃櫼粋€請求來排查問題呢?
解決方案
我們需要一項(xiàng)服務(wù)
- 為每個外部請求分配一個唯一的外部請求 ID。
- 將外部請求 ID 傳遞給所有服務(wù)。
- 在所有日志消息中包含外部請求 ID。
- 集中式記錄和處理外部請求執(zhí)行時操作的信息。
Spring Cloud Slueth 和 Zipkin 服務(wù)器是一類常見的實(shí)現(xiàn)。
d. 健康檢查
問題
實(shí)施微服務(wù)架構(gòu)后,有可能遇到服務(wù)已啟動但無法處理請求的問題。在這種情況下,你如何確保請求不會發(fā)送到那些失敗的實(shí)例?
解決方案
每個服務(wù)都需要有一個端點(diǎn),可用于檢查應(yīng)用程序的健康狀況,例如 /health, 此 API 應(yīng)檢查主機(jī)的狀態(tài)、與其他服務(wù)/基礎(chǔ)設(shè)施的連接以及任何特定邏輯。
Spring Boot Actuator 實(shí)現(xiàn)了一個/health 端點(diǎn),并且該實(shí)現(xiàn)也可以自定義。
5. 跨領(lǐng)域關(guān)注模式(Cross-Cutting Concern)
“cross-cutting concerns”指的是兩個非常不一樣的組件存在一些類似的功能。
a. 外部配置
問題
服務(wù)通常也調(diào)用其他服務(wù)和數(shù)據(jù)庫。對于每個環(huán)境,如 dev、QA、UAT、prod,某些配置屬性可能不同。任何這些屬性的更改都可能需要重新構(gòu)建和重新部署服務(wù)。我們?nèi)绾伪苊庖蚺渲酶亩薷拇a?
解決方案
外部化所有配置,包括憑據(jù)。應(yīng)用程序應(yīng)在啟動時動態(tài)加載它們。
Spring Cloud 配置服務(wù)器提供了將屬性外部化到 GitHub 并將它們作為環(huán)境屬性加載的選項(xiàng)。這些可以在啟動時由應(yīng)用程序訪問,也可以在不重新啟動服務(wù)器的情況下刷新。
b. 服務(wù)發(fā)現(xiàn)模式
問題
當(dāng)微服務(wù)出現(xiàn)后,我們需要解決服務(wù)調(diào)用方面的幾個問題:
那么消費(fèi)者或路由器如何知道所有可用的服務(wù)實(shí)例和位置呢?
解決方案
需要創(chuàng)建一個服務(wù)注冊中心來保存每個生產(chǎn)者服務(wù)的元數(shù)據(jù)。服務(wù)實(shí)例應(yīng)在啟動時注冊到注冊表,并在停止時取消注冊。消費(fèi)者或路由器應(yīng)查詢注冊表并找出服務(wù)的位置。注冊中心還需要對生產(chǎn)者服務(wù)進(jìn)行健康檢查,以確保只有服務(wù)的工作實(shí)例可供通過它使用。有兩種類型的服務(wù)發(fā)現(xiàn):客戶端和服務(wù)器端。
服務(wù)發(fā)現(xiàn)(客戶端)的一個例子是 Netflix Eureka,服務(wù)發(fā)現(xiàn)(服務(wù)器端)的一個例子是 AWS ALB。
c. 斷路器模式
問題
一個服務(wù)一般會調(diào)用其他服務(wù)來查詢數(shù)據(jù),但下游服務(wù)有可能宕機(jī)。這樣做有兩個問題:第一,請求會一直到宕機(jī)的服務(wù),耗盡網(wǎng)絡(luò)資源,降低性能。其次,用戶體驗(yàn)會很差且不可預(yù)測。我們?nèi)绾伪苊饧壜?lián)服務(wù)故障并優(yōu)雅地處理故障呢?
解決方案
消費(fèi)者應(yīng)該通過代理調(diào)用遠(yuǎn)程服務(wù),該代理的行為方式與電路斷路器類似。當(dāng)連續(xù)失敗次數(shù)超過閾值時,斷路器跳閘,并且在超時期限內(nèi),所有調(diào)用遠(yuǎn)程服務(wù)的嘗試都將立即失敗。超時到期后,斷路器允許有限數(shù)量的測試請求通過。如果這些請求成功,斷路器將恢復(fù)正常操作。否則,如果出現(xiàn)故障,超時時間將重新開始。
Netflix Hystrix 是斷路器模式的一個很好的實(shí)現(xiàn)。它還可以在斷路器跳閘時使用回退機(jī)制。這提供了更好的用戶體驗(yàn)。
d. 藍(lán)綠部署模式
問題
使用微服務(wù)架構(gòu),一個應(yīng)用可以有多個微服務(wù)。如果我們停止所有服務(wù),然后部署新版本,停機(jī)時間將會非常長,并且會影響業(yè)務(wù)。此外,回滾將是一場噩夢。我們?nèi)绾伪苊饣驕p少部署期間服務(wù)的停機(jī)時間?
解決方案
可以實(shí)施藍(lán)綠部署策略以減少或消除停機(jī)時間。它通過運(yùn)行兩個相同的生產(chǎn)環(huán)境 Blue 和 Green 來實(shí)現(xiàn)這一點(diǎn)。讓我們假設(shè) Green 是現(xiàn)有的實(shí)時實(shí)例,而 Blue 是應(yīng)用程序的新版本。在任何時候,只有一個環(huán)境處于活動狀態(tài),實(shí)時環(huán)境服務(wù)于所有生產(chǎn)流量。幾乎所有云平臺都提供了實(shí)施藍(lán)綠部署的選項(xiàng)。
還有許多其他與微服務(wù)架構(gòu)一起使用的模式,如 Sidecar、鏈?zhǔn)轿⒎?wù)、分支微服務(wù)、事件溯源模式、持續(xù)交付模式等。如果你還知道其他的微服務(wù)模式,歡迎留言交流。
參考鏈接: https://dzone.com/articles/design-patterns-for-microservices
總結(jié)
以上是生活随笔為你收集整理的微服务的设计模式,你用了几个的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二层数据帧转发过程
- 下一篇: asp.net+mvc+html辅助,A