從 RPC 到服務化框架設計

作者:allendbwu,騰訊 PCG 後臺開發工程師

目前互聯網系統都是微服務化,那麼就需要 RPC 調用,因此本文梳理了從 RPC 基本框架協議到整個服務化框架體系建設中所包含的知識點,重點在於 RPC 框架 和 服務治理能力的梳理,本文定位於一個科普性質的文章,在於讓大家瞭解一個全貌。

一、RPC 基本框架

1-1、RPC 基本框架

理解 RPC

RPC 的概念就是遠程過程調用。我們本地的函數調用,就是 A 方法調 B 方法,然後得到調用的結果,RPC 就是讓你像本地函數調用一樣進行跨服務之間的函數調用。互聯網發展到現在,我們都在講微服務,服務都拆分爲微服務了,那麼相關依賴的調用,就會變成跨服務之間的調用,而他們之間的通信方式就是依靠 RPC。

RPC 基礎結構(RPC 協議)

Nelson 的論文 Implementing Remote Procedure Calls 告訴我們, RPC 協議包括 5 個部分:

  1. Client

  2. Client-stub

  3. RPCRuntime

  4. Server-stub

  5. Server

當 Client 發起一個遠程調用時,它實際上是調用本地的 Stub。本地 stub 負責將調用的接口、方法和參數,通過約定的協議規範進行編碼,並通過本地的 RPCRuntime 進行傳輸,然後將數據包發送到網絡上傳輸出去。當 Server 端的 RPCRuntime 收到請求後,交給 Server-Stub 進行解碼,然後調用 Server 端的函數或者方法,執行完畢就開始返回結果,Server-Stub 將返回結果編碼後,發送給 Client,Client 端的 RPCRuntime 收到結果,發給 Client-Stub 解碼得到結果,返回給 Client。

這裏面分了三個層次:

1-2、RPC 框架的重點

從 RPC 基礎結構中,我們總結出 RPC 框架的重點,包括 4 部分,如下:

1-2-1、數據序列化

序列化就是將數據結構或對象轉換成二進制的過程,也就是編碼的過程,序列化後數據才方便進行網絡傳輸;反序列化就是在序列化過程中所生成的二進制轉換成數據結構或者對象的過程,將二進制轉換爲對象後業務纔好進行後續的邏輯處理。

常見的序列化協議如下:

常見的 RPC 框架如 gRPC、Thrift、Dubbo、RPCX 、Motan 等會支持上述協議中的大部分,尤其是 ProtoBuf 和 JSON 。目前從性能上和使用廣泛度上來看,現在一般推薦使用 ProtoBuf,當然很多自研的框架裏面他們也會自己實現他們自己的序列化協議。

1-2-2、網絡傳輸(網絡通信)

在數據被序列化爲二進制後就可以行網絡傳輸了,網絡傳輸就是我們的數據怎麼傳輸到對方服務器上,目前來說,常見的通信傳輸方式包括 :TCP、UDP、HTTP(HTTP2.0)、QUIC 協議,TCP 是大部分框架都會默認支持的,額外這裏要說明一下,RPCX 支持 QUIC 而 gRPC 支持 HTTP2.0。

QUIC(Quick UDP Internet Connection)是谷歌制定的一種互聯網傳輸層協議,它基於 UDP 傳輸層協議,同時兼具 TCP、TLS、HTTP/2 等協議的可靠性與安全性,可以有效減少連接與傳輸延遲,更好地應對當前傳輸層與應用層的挑戰。QUIC 在應用程序層面就能實現不同的擁塞控制算法,不需要操作系統和內核支持,這相比於傳統的 TCP 協議,擁有了更好的改造靈活性,非常適合在 TCP 協議優化遇到瓶頸的業務。

1-2-3、RPC 調用方式

網絡傳輸只是數據傳輸非常基礎的一方面,從業務上來看,我們發起一次 RPC 調用,那麼還需要 RPC 的調用方式,包括如下三大類:

1-2-4、服務治理

RPC 協議只是定義了 Client 與 Server 之間的點對點調用流程,包括 stub、通信協議、RPC 消息解析等部分。但是在實際應用中,遠程過程調用的時候還需要考慮服務的路由、負載均衡、高可用等問題,而保障服務之間的調用就需要進行服務治理,服務治理基本就涵蓋:服務註冊和發現、限流、降級、熔斷、重試、失敗處理、負載均衡等各種服務治理策略。

到這裏,RPC 框架的重點的 4 大部分就介紹完畢了,現在再來看看,常見的 RPC 框架:

1-3、常見 RPC 框架

RPC 框架就是在 RPC 協議的基礎上,來完善一些偏向業務實際應用的功能,從而滿足不同場景的業務訴求。綜合來看,目前業界的 RPC 框架大致有兩種不同的側重方向,一種偏向於服務治理型,一種偏向於跨語言調用型。

1-3-1、服務治理型 RPC 框架

業界比較出名的服務治理型的 RPC 框架有 Dubbo、DubboX、Motan、RPCX 等。

服務治理型 RPC 框架的特點是功能豐富,提供高性能的遠程調用以及服務發現、服務治理等功能;常用於微服務化的業務系統中,對於特定語言的項目可以十分友好的透明化接入,是當前業界的主流。但缺點是語言耦合度較高,跨語言支持難度較大。

1-3-2、跨語言調用型 RPC 框架

業界比較出名的跨語言調用型的 RPC 框架有 :

跨語言調用型 RPC 框架的重點是關注於服務的跨語言調用,能夠支持我們常見的大部分的語言進行語言無關的調用,非常適合於爲不同語言提供通用遠程服務的場景,但這類框架沒有服務發現、服務治理等機制,使用這些框架的時候需要我們自己來實現服務發現、服務治理等相關策略。

那麼,跨語言調用指的是啥意思呢,具體是:客戶端和服務端可以在各種環境中運行和相互通信,並且可以用框架支持的任何語言編寫(參考 gRPC 官網中的一張圖如下,比如 C++ 的服務可以調用 Ruby 的服務:)

1-3-3、常見 RPC 框架對比

二、通用的服務化框架設計

我們一般講的微服務框架包含了 RPC 框架,微服務體系中最重要的就是 RPC 框架,並且是一般是偏向服務治理的 RPC 框架。微服務需要提供的核心能力包括:微服務架構中通訊的基礎協議 RPC、服務發現與註冊、負載均衡、容錯、熔斷、限流、降級、權限、全鏈路日誌跟蹤。

2-1、微服務框架的核心能力(服務治理策略)

2-1-1、服務註冊與發現

微服務後,服務大量增加,因此我們一定要能夠有一個合適的方案能夠發現對方的所有服務,業界比較常見的服務發現的組件如 zookeeper、etcd、consul 等,基本原理就是先將自己的服務列表到註冊中心註冊,然後再提供服務發現能力。

服務發現機制有服務端發現和客戶端發現兩種實現方式:

2-1-2、服務路由 & 負載均衡

服務路由和服務發現緊密相關,服務路由一般不會設計成一個獨立運行的系統,通常情況下是和服務發現放在一起實現的。在服務路由中,最關鍵的能力就是負載均衡。我們一般常見的負載均衡算法有:隨機路由、輪詢路由、hash、權重、最小壓力路由、最小連接數路由、就近路由等。

從業界來看,負載均衡的實現方案一般可以分爲三類:

2-1-3、服務容錯

負載均衡和容錯是服務高可用的重要手段。服務容錯的設計有個基本原則,就是 “Design for Failure”。常見的服務容錯策略如請求重試、限流、降級、熔斷、隔離

超時與重試

超時機制算是一種最常見的服務容錯模式了,我們發起的任何請求調用,都不可能無限等待,對方服務可能因爲各種原因導致請求不能及時響應,因此超時機制是最基礎並且是必須的。超時可能有網絡超時、也可能是對方服務異常等多種情況。

重試一般和超時模式結合使用,適用於對於下游服務的數據強依賴的場景,通過重試來保證數據的可靠性或一致性,不強依賴的場景不建議使用。在對方服務超時之後,可以根據情況進行重試 (對方服務返回異常就不要重試了)。但是一定注意,重試不能盲目重試,在重試的設計中,我們一般都會引入,Exponential Backoff 的策略,也就是 "指數級退避",每一次重試所需要的 sleep 時間都會指數增加,否則可能會導致拖累到整個系統。

服務限流

限流和降級用來保證核心服務的穩定性;限流是指限制每個服務的最大訪問量、降級是指高峯期對非核心的系統進行降級從而保證核心服務的可用性

限流的實現方式:

分佈式限流和單機限流:

容錯降級

容錯降級可以分爲三大類,從小到大依次是:

熔斷

熔斷設計來源於日常生活中的電路系統,在電路系統中存在一種熔斷器(Circuit Breaker),它的作用就是在電流過大時自動切斷電路。熔斷器一般要實現三個狀態:閉合、斷開和半開,分別對應於正常、故障和故障後檢測故障是否已被修復的場景。

熔斷設計的一般思路是,在請求失敗 N 次後在 X 時間內不再請求,進行熔斷;然後再在 X 時間後恢復 M% 的請求,如果 M% 的請求都成功則恢復正常,關閉熔斷,否則再熔斷 Y 時間,依此循環。

在熔斷的設計中,根據 Netflix 的開源組件 hystrix 的設計,最重要的是三個模塊:熔斷請求判斷算法、熔斷恢復機制、熔斷報警:

隔離

隔離,也就是 Bulkheads 隔板的意思,這個術語是用在造船上的,也就是船艙裏防漏水的隔板。

在服務化框架的隔離設計中,我們同樣是採用類似的技術來讓我們的故障得到隔離。因此這裏的重點就是需要我們對系統進行分離。一般來說,有兩種方式,一種是以服務的類型來做分離,一種是以用戶來做分離。

2-1-4、集羣容錯

在分佈式場景下,我們的服務在集羣中的都是有冗餘的,一個是爲容錯,一個是爲了高併發,針對大量服務實例的情況下,因此就有了集羣容錯的設計。集羣容錯是微服務集羣高可用的保障,它有很多策略可供選擇,包括:

2-2、微服務框架的基礎能力

服務監控和告警

開源代表作:Prometheus + Grafana,遵循 OpenMetrics 規範,基本數據格式分爲 Gauge、Count、Summary、Histogram

分佈式服務 Tracing 跟蹤系統

目前有兩種協議規範:

配置中心

配置中心用來管理大量微服務之間的業務配置,並且是中心化的統一配置中心來進行管理。

遠程日誌

遠程日誌組件的代表作是 ELK 系統:Elasticsearch, Logstash, Kibana。

在微服務架構中,一個客戶端請求的接入,往往涉及到後端一系列服務的調用,如何將這些請求串聯起來?業界常用的方案是採用全局流水號【traceID】串聯起來。通過全局流水號【traceID】,從日誌裏面可以拉出整條調用鏈路。

這裏關於整體鏈路又和 分佈式服務 Tracing 跟蹤系統 關聯起來,Tracing 可以知道整體鏈路的請求質量,遠程日誌 + traceID 可以知道整體鏈路的日誌詳情。

2-3、微服務框架依託的自動化運維能力

微服務框架建設 ok 之後,那麼大量服務怎麼運維,這就依託自動化運維能力,包括如下幾個方面:

業界目前一般採用容器平臺,微服務框架 + K8s 容器平臺 是當今互聯網業務的黃金標準

2-4、小結:自己搭建一個服務化框架的思路

自己搭建一個服務化框架的思路:

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/-T6X-qxjNNonaMJ4hjF3gQ