微服務優化之非同步調用
微服務優化之非同步調用
前一節《微服務優化之並行》,主要從並行的角度來提高微服務的響應時間,本節講一下微服務優化之非同步調用。非同步的前提是對依賴的RPC介面調用,不需要關心其執行結果,對數據沒有強一致性要求,只要能夠達到最終一致性就好。
該種情況下,實現方式一般有兩種:
第一種,對於最終一致性要求很低的情況,比如當用戶投資搶標的情況下,只要用戶的請求到達服務端,並且校驗通過允許搶購,就可以記錄用戶搶購申請,凍結資金,並且立即返回成功,縮短介面響應時間,從而挺高系統吞吐率。然後在系統後台,啟動一個定時任務,定時掃描申請表中的記錄,調用內部標的認購介面,調用外部資金劃撥介面,生成自己劃撥流水,並且更新搶購申請單狀態,完成完整的標的認購,達到最終數據的一致性。
第二種,對於數據實時性要求稍微高一點的,需要藉助於消息隊列,在分散式服務系統中一般會採用分散式消息中間件來輔助完成微服務的非同步化。常用的分散式消息中間件有Kafka、RabbitMQ、RocketMQ、Apache Artemis等等,各個中間的優缺點和用法這裡不多做介紹。
基於消息的非同步該怎麼做呢?當介面接收到客戶端請求後,向消息中間件發送消息,並立即返回成功,靠消息中間件來保證數據的最終一致性。然而這樣做還是不夠的,還需要考慮以下三種情況:
- 如果消息發送失敗了怎麼辦?
- 如果消息發送成功了,消息中間件丟消息,或者消費方業務失敗怎麼辦?
- 如果消息發送成功了,但是返回信息時網路中斷導致消息生產方以為消息發送失敗怎麼辦?
那麼針對以上情況,需要做一下工作:
- 消息生產方需要一個本地事件表,記錄事件流水,事件表至少包含以下狀態:消息發送成功,消息發送失敗,消息發送狀態未知,業務未執行,業務執行成功,業務執行失敗
- 消息生產方需要一個回調介面
- 消息消費方需要一個本地事件表,記錄消費方事件流水,事件表至少包含以下狀態:業務重試次數,業務執行成功,業務執行失敗,業務回滾
基於以上說明,那麼總的執行流程就很清晰了,當客戶端調用我們的RPC時,首先記錄本地事件表,然後發送消息,並根據消息發送結果更新事件表狀態。消息消費方接受消息後,首先記錄本地事件表,然後自行業務邏輯,再根據業務邏輯執行結果更新本地事件表狀態,最後在調用回調介面來更新消息生產方的事件表狀態。最後再通過Job拉取消息生產方的事件表,和消息消費方的事件表對比進行額外的數據補償達到最終的一致性。這樣通過消息中間件達到絕大多數請求的准實時性,同時提高對外介面的響應效率。
推薦閱讀:
※微服務的接入層設計與動靜資源隔離
※docker容器常用命令
※使用 Istio治理微服務入門
※雲原生(CloudNative)將成為應用雲化開發的主流方式
※《微服務設計》閱讀筆記(九)安全