頂尖架構(gòu)師也該掌握的微服務(wù)架構(gòu)設(shè)計(jì)指南
原創(chuàng)【51CTO.com原創(chuàng)稿件】將某個(gè)單一功能的應(yīng)用單元分解成多個(gè)微型服務(wù)單元,這就是微服務(wù)處置傳統(tǒng)單體式架構(gòu)的思想。
但是,實(shí)際上微服務(wù)的架構(gòu)模式遠(yuǎn)不止這么一種。如今,它已經(jīng)成為了各大主流軟件的***開發(fā)方案。
微服務(wù)在提高系統(tǒng)整體性能的同時(shí),也存在著一些自身的局限性。因此對(duì)于一名架構(gòu)設(shè)計(jì)師來說,他需要掌握各種微服務(wù)設(shè)計(jì)模式的特點(diǎn)和應(yīng)用范圍。
下面,在我們開始深入探究之前,先簡(jiǎn)單回顧一下微服務(wù)架構(gòu)的基本概念和整體功能。
微服務(wù)架構(gòu)的設(shè)計(jì)原則
微服務(wù)架構(gòu)的設(shè)計(jì)原則如下:
- 高內(nèi)聚、低耦合。
- 無縫的 API 集成。
- 為每一項(xiàng)服務(wù)分配唯一的資源標(biāo)識(shí)。
- 實(shí)時(shí)流量管理。
- 最小化數(shù)據(jù)表,以優(yōu)化加載。
- 通過內(nèi)/外部 API,執(zhí)行持續(xù)監(jiān)控。
- 為每個(gè)微服務(wù)隔離數(shù)據(jù)的存儲(chǔ)。這對(duì)于限制數(shù)據(jù)的訪問和避免“服務(wù)的耦合”是非常有用的。
例如:基于用戶的分類數(shù)據(jù),我們可以實(shí)施命令查詢的責(zé)任分離(Command Query Responsibility Segregation,CQRS)。
- 去中心化。設(shè)計(jì)微服務(wù)架構(gòu)的首要原則是:將單體結(jié)構(gòu)分解成獨(dú)立的多個(gè)實(shí)體,而這些實(shí)體就被稱為微服務(wù)。
這些微服務(wù)能夠獨(dú)立于其他的系統(tǒng)功能提供服務(wù),用戶對(duì)它們采取的所有編輯、刪除、或在其他地方的使用,都不會(huì)影響到本系統(tǒng)的整體性能。
- 可擴(kuò)展性。微服務(wù)的設(shè)計(jì)目標(biāo)是:性能與效率。在現(xiàn)實(shí)世界中,解決大型系統(tǒng)的可擴(kuò)展性問題,是任何微服務(wù)生態(tài)系統(tǒng)的性能體現(xiàn)。
雖然豐富的技術(shù)功能給大量的數(shù)據(jù)工作帶來了多種數(shù)據(jù)片段,但是如果能恰當(dāng)?shù)貙?shí)施、并使用各種應(yīng)用程序控制器(Application Controllers),則會(huì)讓微服務(wù)架構(gòu)更具可擴(kuò)展性。
- 通過與 DevOps 的集成,實(shí)現(xiàn)持續(xù)交付。DevOps 的多技術(shù)互通與融合,比較適合于微服務(wù)架構(gòu)。在設(shè)計(jì)微服務(wù)架構(gòu)時(shí),我們需要關(guān)注性能和系統(tǒng)效率的提升,這正好契合了 DevOps 的更快交付出方案的理念。
相對(duì)于傳統(tǒng)的單體式設(shè)計(jì),它更適合于部署性、可靠的和可擴(kuò)展性的方案管理。
當(dāng)然,相對(duì)于上述各項(xiàng)原則與優(yōu)勢(shì),微服務(wù)架構(gòu)也有著一定的局限性。不過好在我們擁有多種微服務(wù)的設(shè)計(jì)模式可供選擇,來實(shí)現(xiàn)自己的系統(tǒng)設(shè)計(jì)目標(biāo)。下面讓我們來逐一進(jìn)行討論。
針對(duì)有效協(xié)作的微服務(wù)設(shè)計(jì)模式
高效的微服務(wù)架構(gòu)必須能夠讓多個(gè)微服務(wù)實(shí)現(xiàn)有效的協(xié)作和同步運(yùn)行。
聚合器微服務(wù)設(shè)計(jì)模式
由于會(huì)涉及到多種業(yè)務(wù),我們有必要為最終用戶截獲輸出、并將其予以合并。
對(duì)于用戶來說,如果他們想自行合并數(shù)據(jù),則需要具有對(duì)于系統(tǒng)的大量?jī)?nèi)部知識(shí)。
那么,我們?cè)谠O(shè)計(jì)微服務(wù)架構(gòu)時(shí),為了打破這種單體性,就應(yīng)當(dāng)根據(jù)輸出來進(jìn)行資源的劃分。因此,我們利用聚合器模式,來匯總這些數(shù)據(jù)。
這種方案可以通過兩個(gè)主要組件,來呈現(xiàn)給最終用戶。其中的一種是帶有 API 網(wǎng)關(guān)的復(fù)合式微服務(wù)。它可以匯總數(shù)據(jù),并將其轉(zhuǎn)發(fā)給用戶。
如果您需要在分解的系統(tǒng)中用到各種業(yè)務(wù)功能模塊的話,復(fù)合式微服務(wù)應(yīng)當(dāng)成為您的***。
分支微服務(wù)設(shè)計(jì)模式
此模式擴(kuò)展了聚合器的設(shè)計(jì)模式。在分支模式下,您可以通過兩個(gè)獨(dú)立的(更精確地說是:互斥的)微服務(wù)鏈,來同時(shí)處理請(qǐng)求和響應(yīng)。
這種設(shè)計(jì)模式能夠根據(jù)您的不同業(yè)務(wù)需求,為單個(gè)或多個(gè)服務(wù)鏈提供靈活性。
例如:針對(duì)某個(gè)電子商務(wù)網(wǎng)站或 Web 應(yīng)用程序,我們可能按需接收來自不同微服務(wù)的多個(gè)數(shù)據(jù)源。
后端為前端/API 網(wǎng)關(guān)
從每個(gè)運(yùn)行服務(wù)處獲取數(shù)據(jù),是任何應(yīng)用程序的首要任務(wù)。對(duì)于微服務(wù)架構(gòu)而言,從獨(dú)立的服務(wù)中提取數(shù)據(jù),同樣非常重要。
但是,僅通過一個(gè)用戶界面(UI),從大量的微服務(wù)中獲取用戶手中的資源信息,并不是一件容易的事。
因此,就像企業(yè)里的服務(wù)臺(tái)那樣,我們可以在微服務(wù)架構(gòu)中,用 API 網(wǎng)關(guān)來為所有的交互操作提供統(tǒng)一的入口。
另外,在安全方面,API 網(wǎng)關(guān)也有助于實(shí)現(xiàn)用戶的授權(quán)、和為合適的用戶提供相關(guān)的 API。
因此 API 網(wǎng)關(guān)作為單一的切入點(diǎn),不僅能夠充當(dāng)代理服務(wù)器的作用,將各種請(qǐng)求路由到不同的微服務(wù)那里,還能匯總來自多個(gè)服務(wù)的輸出結(jié)果,并發(fā)送給用戶。
它可以處理多種協(xié)議請(qǐng)求,并按需進(jìn)行轉(zhuǎn)換(例如,實(shí)現(xiàn) HTTPS 與 AMQP 之間的互轉(zhuǎn))。
針對(duì)性能監(jiān)控的微服務(wù)設(shè)計(jì)模式
性能監(jiān)測(cè)是確保微服務(wù)架構(gòu)成功的另一個(gè)重要方面。它有助于衡量系統(tǒng)的效率,并獲悉拖慢系統(tǒng)的罪魁禍?zhǔn)住O铝心J缴婕暗娇捎^測(cè)性的范疇,能夠保障微服務(wù)架構(gòu)設(shè)計(jì)的魯棒性。
日志聚合
微服務(wù)是可以獨(dú)立地、并行地支持多種其他服務(wù)的。而且,它的實(shí)例能夠橫跨各臺(tái)機(jī)器。
同時(shí),每個(gè)服務(wù)都會(huì)根據(jù)其執(zhí)行情況生成一個(gè)日志入口。那么我們?cè)撊绾胃欉@些大量的服務(wù)相關(guān)日志呢?
這正是日志聚合模式的切入點(diǎn)。為了防止出現(xiàn)混亂的局面,我們應(yīng)當(dāng)設(shè)置一個(gè)可以對(duì)所有微服務(wù)實(shí)例進(jìn)行日志聚合的主服務(wù)。而且,這種集中式日志應(yīng)當(dāng)具有搜索和監(jiān)控的功能。
綜合監(jiān)控(或稱語義監(jiān)控)
對(duì)微服務(wù)架構(gòu)的監(jiān)控,是一項(xiàng)繁瑣、但又必要的任務(wù)。當(dāng)有數(shù)百個(gè)服務(wù)同時(shí)運(yùn)行時(shí),要想在日志庫(kù)里查明某個(gè)失敗的根本原因,那就更難了。此時(shí),綜合監(jiān)控可能會(huì)派上用場(chǎng)。
在您進(jìn)行自動(dòng)化測(cè)試時(shí),綜合監(jiān)控能夠幫助您將結(jié)果與生產(chǎn)環(huán)境定期進(jìn)行映射和比較。一旦出現(xiàn)故障,用戶將及時(shí)得到相關(guān)警告。
另外,語義監(jiān)控還能幫助您實(shí)現(xiàn)如下兩方面:
- 監(jiān)測(cè)自動(dòng)化的測(cè)試案例。
- 根據(jù)業(yè)務(wù)需求,檢測(cè)生產(chǎn)環(huán)境中的故障。
同時(shí),隨著系統(tǒng)的負(fù)載和微服務(wù)數(shù)量的增加,對(duì)系統(tǒng)性能的持續(xù)監(jiān)控,并跨服務(wù)發(fā)現(xiàn)潛在的問題,就顯得非常重要了。
我們可以通過指標(biāo)服務(wù)(metric service)來收集各類數(shù)據(jù)。指標(biāo)服務(wù)可以是“推式”和“拉式”兩種形式。
顧名思義,推式服務(wù)(如:AppDynamics)是將捕捉到的數(shù)據(jù)指標(biāo)推送到服務(wù)端;而拉式服務(wù)(如:Prometheus)則負(fù)責(zé)從服務(wù)中拉取對(duì)應(yīng)的數(shù)據(jù)指標(biāo)。
API 健康檢查
微服務(wù)架構(gòu)的設(shè)計(jì)促進(jìn)了各個(gè)服務(wù)之間的相互獨(dú)立,并避免了系統(tǒng)中的任何延遲。
我們知道,API 在網(wǎng)絡(luò)連接中能夠起到基石作用。我們需要通過對(duì) API 的定期健康檢查,來提前發(fā)現(xiàn)各種障礙。
例如,您可能會(huì)經(jīng)常觀察到:某個(gè)微服務(wù)雖然處于啟動(dòng)和和運(yùn)行狀態(tài),卻沒有能力去處理任何請(qǐng)求。
那么,以下便是一些導(dǎo)致 API 故障的因素:
- 服務(wù)器的負(fù)載
- 用戶的使用量
- 各種延遲
- 錯(cuò)誤日志
- 下載量
為了應(yīng)對(duì)上述因素,我們應(yīng)該確保每一個(gè)服務(wù)在運(yùn)行時(shí),都配有一個(gè)健康檢查的特定 API 端點(diǎn)。
例如:我們可以在每個(gè)服務(wù)的末尾,通過追加 HTTP/health 的參數(shù),以返回各個(gè)服務(wù)實(shí)例、主機(jī)、連接和算法邏輯等方面的健康狀況。
同時(shí),服務(wù)注冊(cè)中心需要定期調(diào)用健康檢查的 API 端點(diǎn),以執(zhí)行相關(guān)的健康掃描任務(wù)。
而健康檢查的內(nèi)容則可以包括如下方面:
- 針對(duì)特定應(yīng)用的系統(tǒng)邏輯。
- 主機(jī)的狀態(tài)。
- 連接到其他基礎(chǔ)設(shè)施或任何服務(wù)實(shí)例的連接狀態(tài)。
為業(yè)務(wù)能力而改變一切
在將單體架構(gòu)分解成多個(gè)微服務(wù)的過程中,我們需要根據(jù)實(shí)際情況遵循不同的設(shè)計(jì)模式。
針對(duì)業(yè)務(wù)能力的獨(dú)特微服務(wù)
微服務(wù)的成功應(yīng)該能夠充分體現(xiàn)高內(nèi)聚和低耦合的特點(diǎn)。因此各種服務(wù)需要在抽象出相似功能的基礎(chǔ)上,保持低耦合的狀態(tài)。那么,我們?cè)撊绾螌④浖到y(tǒng)分解成為更小、更獨(dú)立的邏輯單元呢?
我們需要定義微服務(wù)的范圍,從而支持特定的業(yè)務(wù)能力。例如,我們可以將組織的內(nèi)部架構(gòu)分為技術(shù)、營(yíng)銷、公關(guān)、銷售、服務(wù)和運(yùn)維等不同部門,這些不同的職能部門都可以被看作是各個(gè)微服務(wù),而組織本身就是一套系統(tǒng)。
因此,為了保持效率和預(yù)估增長(zhǎng),我們需要按照業(yè)務(wù)能力對(duì)系統(tǒng)進(jìn)行分解,基于各種能力所產(chǎn)生的價(jià)值,區(qū)分不同的業(yè)務(wù)領(lǐng)域。
圍繞相似業(yè)務(wù)能力的微服務(wù)
雖然我們可以按照業(yè)務(wù)能力分類出各種微服務(wù),但是我們?cè)撊绾翁幹媚切┓?wù)中的通用類呢?在此,我們可以用需要干預(yù)的“神類(God Classes)”來分解這些類。
例如,在電子商務(wù)系統(tǒng)中,訂單是一個(gè)共用類,一些諸如訂單號(hào)、訂單管理、訂單退貨、訂單交付等服務(wù)都會(huì)用到它。因此針對(duì)該問題,我們引入了領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Domain-Driven Design,DDD)的微服務(wù)設(shè)計(jì)原則。
在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,我們使用到了各個(gè)子域。這些子域模型應(yīng)當(dāng)被預(yù)定好功能的范圍,即界限上下文(bounded context)。
這些界限上下文作為參數(shù)被用來創(chuàng)建微服務(wù),從而克服了通用類的相關(guān)問題。
刀砍藤蔓的模式
上面我們討論了對(duì)全新單體架構(gòu)概念的分解,下面我們來看看如何將現(xiàn)有的單體系統(tǒng)轉(zhuǎn)換為微服務(wù)架構(gòu)。在此,我們引入刀砍蔓藤的模式。
由于在 Web 應(yīng)用中,經(jīng)常會(huì)涉及到不同域里各個(gè)服務(wù)之間的往返調(diào)用,因此刀砍模式非常適用于對(duì)域的切分。
在該模式下,雖然系統(tǒng)會(huì)出現(xiàn)兩個(gè)域共用一個(gè)相同 URI 的情況,但是一旦某個(gè)服務(wù)完成了轉(zhuǎn)換,我們就會(huì)砍掉其對(duì)應(yīng)的應(yīng)用程序中的現(xiàn)有版本。而且,此過程會(huì)一直持續(xù)下去,直到單體系統(tǒng)不復(fù)存在為止。
針對(duì)優(yōu)化數(shù)據(jù)庫(kù)存儲(chǔ)的微服務(wù)設(shè)計(jì)模式
就微服務(wù)架構(gòu)而言,其松耦合的特性造就了各個(gè)獨(dú)立服務(wù)的部署與擴(kuò)展能力。
但是由于不同的服務(wù)有著不同的存儲(chǔ)需求,因此它們可能需要訪問那些并非存儲(chǔ)在本地的數(shù)據(jù)。
下面讓我們來討論一些根據(jù)不同的需求,所適合采用的主要數(shù)據(jù)庫(kù)設(shè)計(jì)模式。
基于服務(wù)的單獨(dú)數(shù)據(jù)庫(kù)
在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的原則中,基于服務(wù)的單獨(dú)數(shù)據(jù)庫(kù),是將整個(gè)數(shù)據(jù)庫(kù)分配給特定的微服務(wù)。
因此,我們需要按照服務(wù)來事先設(shè)計(jì)好獨(dú)享的數(shù)據(jù)庫(kù)。也就是說,任何其他的外部微服務(wù)都無法訪問,其他未分配給自己的數(shù)據(jù)庫(kù)里的數(shù)據(jù),除非是通過微服務(wù)的 API 網(wǎng)關(guān)方式。
基于服務(wù)的共享數(shù)據(jù)庫(kù)
如果我們只是將上述獨(dú)享數(shù)據(jù)庫(kù)模式運(yùn)用到,將單體架構(gòu)分解成多個(gè)微服務(wù)的場(chǎng)景中,那么難免會(huì)碰到各種麻煩。
因此,我們可以在分解的過程中,對(duì)有限數(shù)量的服務(wù)采用基于服務(wù)的共享數(shù)據(jù)庫(kù)模式。
而這個(gè)數(shù)量一般會(huì)被限制在 2~3 個(gè),否則對(duì)系統(tǒng)的部署、自治性和擴(kuò)展性有所影響。
事件溯源式設(shè)計(jì)模式
當(dāng)應(yīng)用的當(dāng)前狀態(tài)發(fā)生變化時(shí),我們?nèi)绾尾拍艽_保架構(gòu)能夠按需變更,并根據(jù)這些變更實(shí)時(shí)地產(chǎn)生相應(yīng)的事件呢?
事件溯源(Event Sourcing)模式,能夠根據(jù)每個(gè)業(yè)務(wù)實(shí)體的狀態(tài)變化,順次將新的事件追加到事件列表之中。
在系統(tǒng)中,諸如 Customer 這樣的實(shí)體會(huì)產(chǎn)生許多事件,因此我們可以對(duì)實(shí)體的當(dāng)時(shí)狀態(tài)進(jìn)行“截屏式”事件錄入,以便進(jìn)一步查詢或通過自動(dòng)化的狀態(tài)調(diào)整,來優(yōu)化負(fù)載。
命令查詢的責(zé)任分離(CQRS)
對(duì)于基于服務(wù)的數(shù)據(jù)庫(kù)模式而言,由于訪問被限制在了單個(gè)數(shù)據(jù)庫(kù)之中,因此我們很難達(dá)到各種復(fù)雜的查詢效果。那么我們?cè)撊绾螌?shí)現(xiàn)各種基于數(shù)據(jù)庫(kù)系統(tǒng)的聯(lián)合查詢呢?
CQRS 模型將單個(gè)應(yīng)用程序分為命令和查詢兩個(gè)部分:
- 命令部分處理各種創(chuàng)建、更新和刪除之類的請(qǐng)求。
- 查詢則用到了物化視圖(materialized view),而這些視圖是通過事件流來進(jìn)行更新的。
同時(shí),這些事件又是由事件溯源模式所產(chǎn)生,并標(biāo)注了數(shù)據(jù)中的各種變化。
針對(duì)無縫部署的微服務(wù)設(shè)計(jì)模式
在我們實(shí)施微服務(wù)時(shí),難免會(huì)在服務(wù)的調(diào)用上碰到問題,因此我們可以采用橫切(cross-cutting)的模式來簡(jiǎn)化工作。
服務(wù)發(fā)現(xiàn)
由于采用了容器技術(shù),IP 地址往往是被動(dòng)態(tài)地分配的。這就意味著 IP 地址會(huì)隨時(shí)發(fā)生改變,進(jìn)而導(dǎo)致服務(wù)的中斷。此外,用戶需要記住每個(gè)服務(wù)的 URL,而這反而倒退成了緊耦合狀態(tài)。
為了解決該問題,我們需要通過一個(gè)注冊(cè)表,向用戶的請(qǐng)求提供位置信息。服務(wù)實(shí)例在啟動(dòng)時(shí),能夠被注冊(cè)到表中;而在關(guān)閉時(shí),也能被注銷。
此法有助于用戶找出那些可用來查詢的準(zhǔn)確位置。此外,注冊(cè)表通過健康檢查,能夠確保實(shí)例的可用性,進(jìn)而提高系統(tǒng)的性能。
藍(lán)-綠部署
在微服務(wù)架構(gòu)中,一個(gè)系統(tǒng)里往往有著多個(gè)微服務(wù)。如果我們因?yàn)椴渴?、或更新版本而停止所有的服?wù)的話,那么長(zhǎng)時(shí)間的停機(jī)勢(shì)必會(huì)影響整體的生產(chǎn)力。
因此,我們需要在設(shè)計(jì)微服務(wù)架構(gòu)時(shí),通過藍(lán)-綠部署的模式,來避免該問題。
在這個(gè)模式中,我們同時(shí)有著藍(lán)、綠兩套相同且并行的環(huán)境。在任一時(shí)間點(diǎn),只有一套環(huán)境(如藍(lán)色系統(tǒng))真實(shí)在線,并處理著真實(shí)的業(yè)務(wù)流量。
那么在需要進(jìn)行新的部署時(shí),我們將應(yīng)用的***版本上傳到綠色系統(tǒng)中,并將真實(shí)對(duì)外的路由器切換到綠色系統(tǒng)上,以完成更新。
結(jié)論
雖然您不一定會(huì)在自己的微服務(wù)系統(tǒng)中用到上述每一種設(shè)計(jì)模式,但是這些模式都有著它們獨(dú)特的應(yīng)用場(chǎng)景。
作為架構(gòu)師,對(duì)于不同的微服務(wù)架構(gòu)設(shè)計(jì)模式,您需要從應(yīng)用的設(shè)計(jì)階段到生產(chǎn)環(huán)境的維護(hù)階段,持續(xù)進(jìn)行各種評(píng)估、審計(jì)、測(cè)試和實(shí)踐。相信它們?cè)诮o您帶來一致性標(biāo)準(zhǔn)的同時(shí),也能提高您的應(yīng)用的整體可靠性。
【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為51CTO.com】