code

2022年3月7日 星期一

Cloud Native - Service Communication

 At high level

1. external communication (North-South traffic) - 不在同一個K8s cluster之中的service之間的通訊,使用K8s 的exgress controller

2. internal communication (East-West traffic) - 在同一個K8s cluster之中的service之間的通訊,使用K8s 的ingress controller


Protocols

HTTP是最常使用但不見得是最好效能者,優化效能的話,可以透過proxy轉換protocol:



1. Websockets - 適合雙向長時間,透過單一TCP socket建立全雙工低overhead的連線。首先透過HTTP request要求建立WebSocket連線。低延遲也是一個特點。

2. HTTP/2 - binary data protocol,特別適合低延遲高效率的串流通訊。

3. gRPC - 建立在HTTP/2上的lightweight transport protocol,在微服務社群中逐漸受到歡迎,提供包括身份驗證 / 雙向streaming / flow control / blocking bindings / cancellation & timeouts。


Messaging Protocols

cloud native天生使用event-driven / message-based approach,所以我們來看一下兩個主要的protocols:

1. MQTT (Message Queue Telemetry Transport)

通常用在IoT / 機器間 的binary protocol,例如在low-bandwidth環境下的sensor跟gateway的溝通。非常lightweight的publisher/subscriber的scheme。


2. AMQP (Advanced Message Queuing Protocol)

MQTT的rich feature set版本,所以相對不是那麼lightweight跟快速,但是也被許多vendor驗證過是很可靠的,所以在不同vendor的service間溝通可以使用AMQP。


Serialization Considerations

data serialization也是影響效能的一個可能。

1. JSON - 最常使用,但是有較大的memory footprint,所以也會花費計算在serialization / deserialization較大。JSON serializer的選擇就很關乎效能。

2. Protobuf - 由於是binary format,所以效能較佳,幾乎所有現代語言都有相對應的generator。message schema會預先定義在某個proto file,所以每個service預先會有此proto file才知道如何serialize/deserialize data。


Idempotency (冪等性)

service對任意的request每次都能產出一樣結果的話,稱為idempotency,一個可能發生不idempotency的場景是,某個API因為網路不穩而重新送了兩次request,造成service端重複process了同樣的data兩次,若是不符合idempotency的API有可能會造成錯誤。常見的解決方法是加上unique request ID,所以已經process過的ID就不會再process,避免了non-idempotency的可能,也稱為de-duping。


Request/Response

synchronous pattern就沒什麼好說的,一來一往等待:


asynchronous pattern的話,就要確保request方知道目前的response是對哪一個request的回應,這可以用message queue + correlation id (CID) 來達成:



publisher/subscriber

cloud native app中最常見的async communication pattern,多個subscriber訂閱某個topic,當publisher push message時,中間角色的broker對所有subscriber廣播出去。

- pub / sub 是完全獨立解耦合的

- event driven design


注意事項

1. async communication不保證接收到訊息的順序,所以需要注意idempotency issue

2. 如果care接收到訊息的順序,可以善用messaging system的內建ordering functionality或是使用priority queue pattern


要選擇Pub/Sub or Request/Response?

case by case依照application需求而定,例如以下為同一個cloud native app採用兩種approach:


data flow是 S1收到client async request後,處理完後又對S2 / S3也發出request。S3處理完後,向S4 / S5發出request。

Request/Response - S3要等待S4/S5處理完才能respond to S1,有可能因為fail而timeout,但是client端可能要很久之後才發現fail,而且必須處理idempotency,免得客戶多發了很多次request造成資料異常。換言之,request/response對每個參與的service來說是高度耦合的。


Pub/Sub - 較低耦合度,透過中間pub/sub系統例如 Redis/RabbitMQ/Apache Kafka。


Synchronous vs Asynchronous

所有的service instance基本上就是一個process,彼此間的溝通就是IPC (interprocess communication)機制,用synchronous communication有主要三個問題:

1. scale up時會因為等待response而被block住,容易產生資源瓶頸

2. response延遲時間是喔死有節點的延遲加總,所以其中一個慢,會讓client端的整體response latency高。

3. 錯誤累積,這類似2. 的問題。


所以cloud native app基本上是採用asynchronous communication。


沒有留言:

張貼留言