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。