微服務架構的通訊設計模式

語言: CN / TW / HK

昨天我們一起學習的微服務資料模式,今天我們來學習一下微服務的通訊設計模式,通訊是保證服務請求核心要素,選擇合適的一個通訊協議對系統來說可以達到事半功倍。

一、RPC呼叫模式

目前各種微服務通訊社群上,很多種支援RPC模式。有同步請求/響應通訊機制,例如基於 HTTP 的 REST 或 GraphQL,或 gRPC。或者可以使用非同步的、基於訊息的通訊機制,例如 AMQP(高階訊息佇列協議)或 STOMP(簡單/流式面向文字的訊息傳遞協議)。此外,還有許多不同的訊息格式。這些格式可以是可讀的,例如 JSON 和 XML。他們還可以使用更高效的二進位制格式,例如 Avro 或 Protobuf。

1.1 RPC 選擇因素

在選擇 RPC 機制之前,考慮一下服務與其客戶端之間的互動方式是很有必要的。客戶服務互動有兩個維度。

1.1.1 一對一還是一對多

一對一 :每個客戶端請求都由一個服務處理。

一對多 :每個客戶端請求都由多個服務處理。

1.1.2 同步的還是非同步的

同步:客戶端在等待服務響應時可能會阻塞。

非同步 :客戶端不會阻塞,並且響應(如果有)並不是立即傳送。

1.2 一對一互動

同步請求/響應 :服務客戶端請求服務並等待響應。服務的緊密耦合是這種互動方式的結果。

非同步請求/響應 :服務客戶端向服務傳送請求,服務非同步回覆。

單向通知 :客戶端向服務傳送請求,但不期待響應。

1.3 一對多互動

非同步釋出/訂閱 :客戶端釋出通知訊息,由一個或多個訂閱服務使用。

非同步釋出/非同步響應 :在這種情況下,客戶端釋出一條訊息,然後等待來自感興趣服務的響應。

1.4 訊息格式

RPC 本質上是一種訊息交換。其中一個重要的設計是訊息包含資料的格式。訊息格式的選擇會影響 RPC 的效率、API 的可用性及其可演化性。

訊息格式有兩種主要型別:文字和二進位制。

1.4.1 基於文字的訊息格式

JSON 和 XML 是最流行的基於文字的格式。

基於文字的訊息格式的優點

可讀性高,可自我描述。

基於文字的訊息格式的缺點

訊息很冗長。

除了它們的值之外,沒有必要的屬性及其他標籤都會包含其中。

解析文字效能開銷很大。

1.4.2 二進位制訊息格式

Thrift、Protocol Buffers (Protobuf) 和 Avro 是最流行的二進位制格式。

二進位制訊息格式的優點

元資料很少,因此有效負載很小。

比基於文字的訊息解析要快。

二進位制訊息格式的缺點

可讀性差,不可自我描述

二、遠端過程呼叫模式

當客戶端請求服務時,服務會處理請求併發迴響應。雖然一些客戶端可能會在等待響應時阻塞,但其他客戶端可能具有反應性、非阻塞架構。

代理介面通常封裝底層通訊協議。

有多種通訊協議可供選擇,例如 REST、gRPC 和 GraphQL 等。

三、使用同步模式進行通訊

3.1 REST(代表性狀態轉移)

REST 基於資源的概念,它表示單個業務物件。HTTP(超文字傳輸​協議)用於實現 REST。REST 使用 HTTP 來操作由 URL 引用的資源。

3.2 HTTP 呼叫方式

GET: GET 方法向特定的資源發出請求。GET方法不應當被用於產生“副作用”的操作中,例如在Web Application中,其中一個原因是GET可能會被網路蜘蛛等隨意訪問

HEAD: HEAD 方法向伺服器索與GET請求相一致的響應,只不過響應體將不會被返回。這一方法可以在不必傳輸整個響應內容的情況下,就可以獲取包含在響應小訊息頭中的元資訊。

POST: POST請求資料被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。

PUT: PUT 方法用請求有效負載替換目標資源的所有當前表示。

DELETE: DELETE 方法請求伺服器刪除Request-URL所標識的資源

CONNECT: CONNECT 方法建立由目標資源標識的伺服器的隧道。

OPTIONS: OPTIONS 方法描述了目標資源的通訊選項。

TRACE: TRACE 方法沿到目標資源的路徑執行訊息環回測試。

PATCH: PATCH 方法將部分修改應用於資源。

3.3 指定 REST API

API 必須使用 IDL(介面定義語言)定義。最流行的 REST IDL 之一是開放 API 規範,它是從Swagger開源專案演變而來的。

3.4 挑戰一:在單個請求中獲取多個資源

由於 REST API 通常基於業務物件,因此在一個請求中請求多個相關物件是設計 REST API 時的常見難題之一。客戶端必須至少對相關物件發出多次請求。

使用查詢引數,API 可以使客戶端在獲取資源時檢索相關資源。由於這種方法缺乏可擴充套件性,GraphQL和Netflix Falcor等替代 API 技術變得越來越受歡迎。

3.5 挑戰二:對映操作到 HTTP 動詞

另一個常見的 REST API 設計問題是將要對業務物件執行的操作對映到 HTTP 請求上。REST API 使用 PUT 來更新,但是有多種方法可以操作訂單,包括取消訂單、修改訂單等。一種解決方案是定義一個子資源,如 /orders/{orderId}/cancel 或 /orders/{orderId}/revise 以更新資源的特定方面或在 URL 查詢引數中指定動詞。但這些解決方案並不是真正的 RESTful。

由於這個問題,REST 的替代品(例如gRPC)越來越受歡迎。

3.5 REST 的優勢

目前很多微服務框架都支援REST,實現起來相對容易

Postman 等外掛可以輕鬆地在瀏覽器中測試 HTTP API。

它支援直接請求/響應通訊。

3.6 REST 的缺點

僅支援請求/響應通訊。

由於要求客戶端和伺服器同時線上,可用性降低。

客戶端必須使用服務發現來發現服務例項的 URL。

在一個請求中獲取多個資源可能具有挑戰性。

將多個更新操作對映到 HTTP 動詞可能具有挑戰性。

四、gRPC

由於 HTTP 僅提供一組有限的請求方式,因此設計支援多個更新操作的 REST API 可能具有挑戰性。

谷歌推出的跨語言客戶端和伺服器的框架 gRPC 可以解決這個問題。使用基於協議緩衝區的 IDL 定義 gRPC API,這是 Google 用於序列化結構化資料的語言設計機制。是一種同步通訊機制。使用 HTTP/2,客戶端和伺服器以協議緩衝區格式交換二進位制訊息。

4.1 gRPC 的優勢

易於設計具有豐富更新操作集的 API 。

訊息格式緊湊且高效。

雙向流使 RPC 和訊息傳遞成為可能。

它支援以多種語言編寫的客戶端和服務的互操作性。

4.2 gRPC 的缺點

JS 客戶端必須做更多的工作來使用基於 gRPC 的 API,而不是基於 REST/JSON 的 API。

五、GraphQL

GraphQL 解決了使用單個請求獲取多個資源的問題。GraphQL 主要用於從客戶端應用程式查詢資料庫。在後端,GraphQL 向 API 指定如何將資料呈現給客戶端。GraphQL 重新定義了開發人員使用 API 的方式,提供更大的靈活性和更快的上線速度;改進了客戶端-伺服器互動,使前者能夠進行精確的資料請求,並只獲得他們需要的資料。

GraphQL 伺服器為客戶端提供模式:可以請求的資料模型。

5.1 GraphQL 的優勢

客戶端可以準確地從伺服器指定他們需要什麼,伺服器將以可預測的方式反饋該資料。

API 使用者確切地知道哪些資料可用以及它是什麼形式,因為它是強型別的。

5.2 GraphQL 的缺點

無論查詢成功與否,它總是返回一個 HTTP 狀態碼 200。

沒有內建快取支援

它比 REST 更復雜

六、使用非同步訊息傳遞模式進行通訊

使用訊息傳遞時,服務會非同步交換訊息。基於訊息的應用程式通常使用像 RabbitMQ 這樣的訊息代理,充當服務之間的中介。服務客戶端通過向服務傳送訊息來向服務發出請求。如果期望響應,服務例項將向客戶端傳送單獨的訊息。由於通訊是非同步的,客戶端不會等待響應。相反,客戶端是假設不會立即收到響應的。

6.1 單向通知

非同步訊息傳遞使實現單向通知變得容易。通常,客戶端向服務擁有的點對點通道傳送訊息。服務訂閱頻道處理訊息。沒有響應被髮回。

6.2 釋出/訂閱

釋出/訂閱互動樣式內置於訊息傳遞中。客戶端將訊息釋出到由多個訂閱者讀取的釋出-訂閱通道。

6.3 釋出/非同步響應

結合了釋出/訂閱和請求/響應的元素,形成了更高層次的互動風格。客戶端將指定回覆通道頭的訊息釋出到釋出-訂閱通道。消費者將包含相關 id 的回覆訊息寫入回覆通道。客戶端利用相關 id 將回復訊息與收集響應的請求進行匹配。