微服務的進程間通訊(IPC)
微服務的進程間通訊(IPC)
本文介紹了幾種典型的微服務間通訊方式,並提供了幾種相應的實現方式。
微服務的進程間通訊架構圖:
術語
IPC:進程間通訊
MSA:微服務架構
概述
服務間通訊包含兩大類:
- 基於同步請求/響應的通訊,如REST,gRPC
- 基於非同步消息的通訊,如AMQP或STOMP
通訊視角
視角 #1
-
一對一通訊
-
一對多通訊
視角 #2
- 同步通訊
- 非同步通訊
一對一通訊類型
- 請求/響應通訊
- 非同步請求響應
- 單方面通知
一對多通訊類型
- 發布/訂閱
- 發布/非同步響應
APIs
服務API是服務端和客戶端之間的合約。
- 理想情況下,首先應該定義服務的介面,然後再實現服務
服務APIs使用版本語法來命名APIs的版本。版本語法包含三個部分:MAJOR.MINOR.PATCH。
消息格式
IPC的本質是消息的交互。消息有兩種格式:文本格式和二進位格式。
- 文本格式:JSON,XML
- 二進位格式:Avro,Protobuf和Thrift
在實現時必須注意消息格式的跨語言協作,因此不推薦使用JavaSerializer。
RPC
遠程調用服務的方法,但對調用者來說,就像使用本地方法一樣。
流程:
- 客戶端的業務邏輯調用RPI代理介面
- RPI代理通過網路調用RPI服務,即調用服務端的業務邏輯
- 服務端將結果返回給RPI代理,最終由RPI代理返回給客戶端的業務邏輯。
REST
REST是一種理念,而非協議。REST用到了HTTP。
REST的一個主要理念是資源,它代表一個單獨的業務實體,如Movie,Customer等,或一個對象集合。
REST使用HTTP verb來操作資源,如:
POST /movies
: Create a moviePUT /movies
: Update a movieGET /movies
: Get all moviesGET /movies/{movieId}
: Get a movie
gRPC
gRPC是一個基於二進位的消息協議,因此必須優先處理API(定義API)。首先使用IDL定義介面,然後編譯生成期望語言的客戶端和服務端stubs。
斷路器
是一個RPI代理,用於在連續發送的錯誤超過一定閾值時,在一定時間內拒絕調用。
常用的斷路器庫如下:
- Netflix Hystrix ( Java )
- Polly ( .Net )
- Hystrix Go (Go lang)
API通訊的健壯性
為了構建同步通訊的健壯性,需要考慮如下模式:
- 網路超時
- 重試
- 斷路器
- 回滾
- 可靠性測試
服務發現
問題
服務A需要通過API調用服務B,因此服務A需要知道服務B的地址。
傳統方式
最簡單的方式是靜態配置實例的網路地址,這樣調用者可以在配置文件中指定該地址。
傳統方式的問題
現在,由於在自動擴容、失敗和升級時會動態創建服務實例,並為實例動態分配網路位置,因此引出了服務發現的需求。
服務發現
服務發現的概念非常簡單,最主要的組件是服務註冊表,存儲了應用服務實例的網路位置。
服務發現的兩種主要實現方式:
- 服務端和客戶端直接與服務註冊表交互
- 通過部署平台(如kubernetes)進行交互
服務發現模式:
- 自註冊
- 客戶端發現
- 服務端發現
非同步消息
基於消息的應用通常會使用一個消息代理(broker),作為服務間的中間人。另一種方式是使用無消息代理架構。
概念
發送端會向一個channel寫入消息,接收者會從該channel中讀取消息。
消息
消息包含首部和消息體。
首部是一個鍵值對集合,此外還包含一個唯一消息Id(來自發送端或由消息基礎設施生成)。
消息體包含需要發送的數據。
消息類型
- 文檔
- 目錄
- 事件
Channels
消息通過channel進行交互。channel有兩種類型:
- 點到點channel
- 發布訂閱channel
非同步通訊實現
非同步請求響應
發布訂閱
無消息代理
- 服務可以直接進行交互
- ZeroMQ就是一個典型的無消息代理技術
基於消息代理的通訊
消息代理是所有消息流的中間人。
好處
- 發送端不需要知道消費端的位置
- 在消息被消費者處理前,消息代理會對消息進行快取
典型的開源消息代理
- ActiveMQ
- RabbitMQ
- Apache Kafka
在選擇消息代理時需要考慮的因素
- 支援的程式語言
- 支援的消息標準
- 消息順序
- 保證消息的發送
- 持久化
- 穩定性
- 可擴展性
- 延遲
- 產品競爭力