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