微服務(wù)中 REST 與消息傳遞對比
微服務(wù)架構(gòu)是一種既定模式,用于構(gòu)建由松散耦合模塊組成的復(fù)雜系統(tǒng)。它是過去幾年中最受關(guān)注的軟件架構(gòu)趨勢之一。將一個大型的、相互依賴的系統(tǒng)分解成許多小的、輕量級的模塊,這似乎是一個非常簡單的想法,這些模塊可以使軟件管理更容易。
這里有一個要點(diǎn):在將整體應(yīng)用程序分解為小模塊之后,應(yīng)該如何以有意義的方式將它們連接在一起?不幸的是,這個問題沒有單一的正確答案,但通常情況下,有幾種方法取決于應(yīng)用程序和個別用例。
微服務(wù)中使用的兩種常見協(xié)議是使用資源 API 的 HTTP 請求/響應(yīng)和跨多個微服務(wù)通信更新時(shí)的輕量級異步消息傳遞。讓我們探索這些協(xié)議。
通訊類型
微服務(wù)可以通過多種不同的通信模式進(jìn)行通信,每種模式都針對不同的用例。這些類型的通信主要可以分為兩個維度。第一個維度定義通信協(xié)議是同步的還是異步的:
同步與異步通信第二個維度定義了通信是有一個接收者還是多個接收者:
微服務(wù)之間最常見的通信類型是在調(diào)用 REST API 時(shí)使用同步協(xié)議(如 HTTP/HTTPS)的單接收器通信。微服務(wù)通常使用消息協(xié)議在微服務(wù)之間進(jìn)行異步通信。這種異步通信可能涉及單個接收器或多個接收器,具體取決于應(yīng)用程序的需要。
表征狀態(tài)轉(zhuǎn)移
表述性狀態(tài)傳輸 (REST) 是一種流行的請求和響應(yīng)通信架構(gòu)風(fēng)格,它可以作為同步通信類型的一個很好的例子。這是基于 HTTP 協(xié)議,包含 GET、POST、PUT、DELETE 等動詞。在這種通信模式中,調(diào)用者等待服務(wù)器的響應(yīng)。
圖 1:基于 REST API 的通信
REST 是服務(wù)間通信最常用的架構(gòu)風(fēng)格,但在涉及微服務(wù)架構(gòu)時(shí),嚴(yán)重依賴這種類型的通信會產(chǎn)生一些負(fù)面影響:
- 多次往返(延遲) ——客戶端通常需要執(zhí)行多次到服務(wù)器的行程以獲取客戶端所需的所有數(shù)據(jù)。每個端點(diǎn)指定固定數(shù)量的數(shù)據(jù),并且在許多情況下,該數(shù)據(jù)只是客戶端填充其頁面所需的數(shù)據(jù)的一個子集。
- 阻塞——調(diào)用 REST API 時(shí),客戶端被阻塞并等待服務(wù)器響應(yīng)。如果應(yīng)用程序線程正在處理其他并發(fā)請求,這可能會損害應(yīng)用程序性能。
- 緊耦合——客戶端和服務(wù)器需要相互了解。隨著時(shí)間的推移,它會增加復(fù)雜性并降低可移植性。
訊息
消息在遵循異步協(xié)議的微服務(wù)架構(gòu)中被廣泛使用。在此模式中,服務(wù)發(fā)送消息而不等待響應(yīng),并且一個或多個服務(wù)異步處理消息。異步消息傳遞提供了許多好處,但也帶來了冪等性、消息排序、毒消息處理和消息代理的復(fù)雜性等挑戰(zhàn),這些消息代理必須具有高可用性。
重要的是要注意異步 I/O 和異步協(xié)議之間的區(qū)別。異步 I/O意味著調(diào)用線程在執(zhí)行 I/O 操作時(shí)不會被阻塞。這是軟件設(shè)計(jì)方面的一個實(shí)現(xiàn)細(xì)節(jié)。異步協(xié)議意味著發(fā)送方不等待響應(yīng)。
圖 2:基于消息的通信
異步消息傳遞與同步消息傳遞相比有一些優(yōu)勢:
- 松耦合——消息生產(chǎn)者不需要知道消費(fèi)者。
- 多個訂閱者——使用發(fā)布者/訂閱者 (pub/sub) 模型,多個消費(fèi)者可以訂閱接收事件。
- 彈性或故障隔離——如果消費(fèi)者發(fā)生故障,生產(chǎn)者仍然可以發(fā)送消息。當(dāng)消費(fèi)者從失敗中恢復(fù)時(shí),消息將被拾取。這在微服務(wù)架構(gòu)中特別有用,因?yàn)槊總€微服務(wù)都有自己的生命周期。
- 非阻塞——生產(chǎn)者和消費(fèi)者可以按照自己的節(jié)奏發(fā)送和處理消息。
盡管異步消息傳遞有很多優(yōu)點(diǎn),但它也有一些折衷:
- 與消息傳遞基礎(chǔ)設(shè)施的緊密耦合——使用特定的供應(yīng)商/消息傳遞基礎(chǔ)設(shè)施可能會導(dǎo)致與該基礎(chǔ)設(shè)施的緊密耦合。以后可能很難切換到另一個供應(yīng)商/消息基礎(chǔ)設(shè)施。
- 復(fù)雜性——處理異步消息可能不像設(shè)計(jì) REST API 那樣容易。必須通過去重或使操作冪等來處理重復(fù)的消息。使用異步消息傳遞很難實(shí)現(xiàn)請求-響應(yīng)語義。要發(fā)送響應(yīng),需要另一個隊(duì)列以及關(guān)聯(lián)請求和響應(yīng)消息的方法。調(diào)試也很困難,因?yàn)楹茈y確定服務(wù) A 中的哪個請求導(dǎo)致了服務(wù) B 中的錯誤行為。
異步消息傳遞已經(jīng)成熟為多種消息傳遞模式。這些模式適用于分布式系統(tǒng)的多個部分必須以可靠和可擴(kuò)展的方式相互通信的場景。讓我們來看看其中的一些模式。
發(fā)布/訂閱模式
發(fā)布/訂閱模式意味著發(fā)布者將消息發(fā)送到消息代理上的通道。一個或多個訂閱者訂閱頻道并以異步方式從頻道接收消息。當(dāng)微服務(wù)需要向大量消費(fèi)者廣播信息時(shí),此模式很有用。
圖 3:發(fā)布/訂閱模式
發(fā)布/訂閱模式具有以下優(yōu)點(diǎn):
- 它解耦了需要通信的發(fā)布者和訂閱者。發(fā)布者和訂閱者可以獨(dú)立管理,即使一個或多個訂閱者離線也可以管理消息。
- 它增加了可擴(kuò)展性并提高了發(fā)布者的響應(yīng)能力。發(fā)布者可以快速將消息發(fā)布到輸入通道,然后返回其核心處理職責(zé)。消息傳遞基礎(chǔ)設(shè)施負(fù)責(zé)確保將消息傳遞給感興趣的訂閱者。
- 它為微服務(wù)提供 關(guān)注點(diǎn)分離。每個微服務(wù)都可以專注于其核心職責(zé),而消息代理處理將消息可靠地路由到多個訂閱者所需的一切。
使用這種模式有一些缺點(diǎn):
- 發(fā)布/訂閱模式在發(fā)布者傳遞給訂閱者的消息中引入了高度語義耦合。數(shù)據(jù)結(jié)構(gòu)一旦建立,通常很難改變。要更改消息結(jié)構(gòu),必須更改所有訂閱者以接受更改后的格式。如果訂戶是外部的,這可能很困難或不可能。
- 發(fā)布/訂閱模式的另一個缺點(diǎn)是很難衡量訂閱者的健康狀況。發(fā)布者不知道收聽消息的系統(tǒng)的健康狀況。
- 隨著發(fā)布/訂閱系統(tǒng)的擴(kuò)展,代理通常成為消息流的瓶頸。負(fù)載激增會減慢發(fā)布/訂閱系統(tǒng)的速度,訂閱者的響應(yīng)時(shí)間可能會出現(xiàn)峰值。
基于隊(duì)列的模式
在基于隊(duì)列的模式中,發(fā)送方將消息發(fā)布到包含接收方所需數(shù)據(jù)的隊(duì)列。隊(duì)列充當(dāng)緩沖區(qū),存儲消息直到它被接收者檢索。接收者從隊(duì)列中檢索消息并按照自己的節(jié)奏處理它們。此模式對于使用容易過載的服務(wù)的任何應(yīng)用程序都很有用。
圖 4:基于隊(duì)列的模式
基于隊(duì)列的模式有以下優(yōu)點(diǎn):
- 它可以幫助最大限度地提高可擴(kuò)展性,因?yàn)殛?duì)列數(shù)量和服務(wù)數(shù)量都可以擴(kuò)展以滿足需求。
- 它可以幫助最大限度地提高可用性。生產(chǎn)者或消費(fèi)者中出現(xiàn)的延遲不會對服務(wù)產(chǎn)生直接或直接的影響,即使消費(fèi)者不可用或處理消息的負(fù)載很重,服務(wù)也可以繼續(xù)將消息發(fā)布到隊(duì)列中。
使用這種模式有一些缺點(diǎn):
- 當(dāng)消費(fèi)者從隊(duì)列中收到一條消息時(shí),該消息在隊(duì)列中不再可用。如果消費(fèi)者未能處理消息,消息將丟失并且可能需要在消費(fèi)者中回滾。
- 消息隊(duì)列不是開箱即用的。我們需要創(chuàng)建、配置和監(jiān)控它們。當(dāng)系統(tǒng)擴(kuò)展時(shí),它可能會導(dǎo)致操作復(fù)雜性。
簡化消息傳遞基礎(chǔ)架構(gòu)的關(guān)鍵
異步通信通常通過消息代理進(jìn)行管理。在為異步通信選擇正確的消息傳遞基礎(chǔ)設(shè)施時(shí),需要考慮一些因素:
- 可擴(kuò)展性——消息代理負(fù)載激增時(shí)自動擴(kuò)展的能力
- 數(shù)據(jù)持久性——在重啟/失敗的情況下恢復(fù)消息的能力
- 消費(fèi)者能力——經(jīng)紀(jì)人是否可以管理一對一和/或一對多消費(fèi)者
- 監(jiān)控——是否具備監(jiān)控能力
- 推送和拉取隊(duì)列——通過消息隊(duì)列處理推送和拉取傳遞的能力
- 安全性——對消息隊(duì)列和主題進(jìn)行適當(dāng)?shù)纳矸蒡?yàn)證和授權(quán)
- 自動故障轉(zhuǎn)移——能夠在一個代理發(fā)生故障時(shí)自動連接到故障轉(zhuǎn)移代理而不影響發(fā)布者/消費(fèi)者
結(jié)論
微服務(wù)越來越成為設(shè)計(jì)可擴(kuò)展和彈性系統(tǒng)的實(shí)際方法。微服務(wù)之間的所有通信都沒有單一的方法。RESTful API 提供請求-響應(yīng)模型以在服務(wù)之間進(jìn)行通信,而異步消息傳遞則在不同服務(wù)之間提供更具可擴(kuò)展性的生產(chǎn)者-消費(fèi)者關(guān)系。盡管微服務(wù)可以通過消息傳遞和 REST API 相互通信,但消息傳遞架構(gòu)是提高敏捷性和快速移動的理想選擇。它們常見于使用微服務(wù)的現(xiàn)代應(yīng)用程序或任何具有解耦組件的應(yīng)用程序中。
在為您的微服務(wù)選擇合適的通信方式時(shí),請務(wù)必將消費(fèi)者的需求與一種或多種通信類型相匹配,從而為您的服務(wù)提供強(qiáng)大的接口。