從0開始學微服務:14 開源RPC框架如何選型?

從0開始學微服務:14 開源RPC框架如何選型?

我給你講解了 RPC 遠程調用的原理,簡單回顧一下一個完整的 RPC 框架主要有三部分組成:通信框架、通信協議、序列化和反序列化格式。根據我的經驗,想要開發一個完整的 RPC 框架,並且應用到線上生產環境,至少需要投入三個人力半年以上的時間。這對於大部分中小團隊來說,人力成本和時間成本都是不可接受的,所以我建議還是選擇開源的 RPC 框架比較合適。

那麼業界應用比較廣泛的開源 RPC 框架有哪些呢?

簡單劃分的話,主要分為兩類:一類是跟某種特定語言平臺綁定的,另一類是與語言無關即跨語言平臺的。

跟語言平臺綁定的開源 RPC 框架主要有下面幾種。

  • Dubbo:國內最早開源的 RPC 框架,由阿里巴巴公司開發並於 2011 年末對外開源,僅支持 Java 語言。
  • Motan:微博內部使用的 RPC 框架,於 2016 年對外開源,僅支持 Java 語言。
  • Tars:騰訊內部使用的 RPC 框架,於 2017 年對外開源,僅支持 C++ 語言。
  • Spring Cloud:國外 Pivotal 公司 2014 年對外開源的 RPC 框架,僅支持 Java 語言,最近幾年生態發展得比較好,是比較火的 RPC 框架。

而跨語言平臺的開源 RPC 框架主要有以下幾種。

  • gRPC:Google 於 2015 年對外開源的跨語言 RPC 框架,支持常用的 C++、Java、Python、Go、Ruby、PHP、Android Java、Objective-C 等多種語言。
  • Thrift:最初是由 Facebook 開發的內部系統跨語言的 RPC 框架,2007 年貢獻給了 Apache 基金,成為 Apache 開源項目之一,支持常用的 C++、Java、PHP、Python、Ruby、Erlang 等多種語言。

所以很明顯,如果你的業務場景僅僅侷限於一種語言的話,可以選擇跟語言綁定的 RPC 框架中的一種;如果涉及多個語言平臺之間的相互調用,就應該選擇跨語言平臺的 RPC 框架。

針對每一種 RPC 框架,它們具體有何區別?該如何選擇呢?接下來,我就從每個框架的實現角度來具體給你講解。當你知道了他們的具體實現,也就能知道他們的優缺點以及適用場景了。

限定語言平臺的開源 RPC 框架

1. Dubbo

先來聊聊 Dubbo,Dubbo 可以說是國內開源最早的 RPC 框架了,目前只支持 Java 語言,它的架構可以用下面這張圖展示。

從0開始學微服務:14 開源RPC框架如何選型?

從圖中你能看到,Dubbo 的架構主要包含四個角色,其中 Consumer 是服務消費者,Provider 是服務提供者,Registry 是註冊中心,Monitor 是監控系統。

具體的交互流程是 Consumer 一端通過註冊中心獲取到 Provider 節點後,通過 Dubbo 的客戶端 SDK 與 Provider 建立連接,併發起調用。Provider 一端通過 Dubbo 的服務端 SDK 接收到 Consumer 的請求,處理後再把結果返回給 Consumer。

可以看出服務消費者和服務提供者都需要引入 Dubbo 的 SDK 才來完成 RPC 調用,因為 Dubbo 本身是採用 Java 語言實現的,所以要求服務消費者和服務提供者也都必須採用 Java 語言實現才可以應用。

我們再來看下 Dubbo 的調用框架是如何實現的。

  • 通信框架方面,Dubbo 默認採用了 Netty 作為通信框架。
  • 通信協議方面,Dubbo 除了支持私有的 Dubbo 協議外,還支持 RMI 協議、Hession 協議、HTTP 協議、Thrift 協議等。
  • 序列化格式方面,Dubbo 支持多種序列化格式,比如 Dubbo、Hession、JSON、Kryo、FST 等。

2. Motan

Motan 是國內另外一個比較有名的開源的 RPC 框架,同樣也只支持 Java 語言實現,它的架構可以用下面這張圖描述。

從0開始學微服務:14 開源RPC框架如何選型?

Motan 與 Dubbo 的架構類似,都需要在 Client 端(服務消費者)和 Server 端(服務提供者)引入 SDK,其中 Motan 框架主要包含下面幾個功能模塊。

  • register:用來和註冊中心交互,包括註冊服務、訂閱服務、服務變更通知、服務心跳發送等功能。Server 端會在系統初始化時通過 register 模塊註冊服務,Client 端會在系統初始化時通過 register 模塊訂閱到具體提供服務的 Server 列表,當 Server 列表發生變更時也由 register 模塊通知 Client。
  • protocol:用來進行 RPC 服務的描述和 RPC 服務的配置管理,這一層還可以添加不同功能的 filter 用來完成統計、併發限制等功能。
  • serialize:將 RPC 請求中的參數、結果等對象進行序列化與反序列化,即進行對象與字節流的互相轉換,默認使用對 Java 更友好的 Hessian 2 進行序列化。
  • transport:用來進行遠程通信,默認使用 Netty NIO 的 TCP 長鏈接方式。
  • cluster:Client 端使用的模塊,cluster 是一組可用的 Server 在邏輯上的封裝,包含若干可以提供 RPC 服務的 Server,實際請求時會根據不同的高可用與負載均衡策略選擇一個可用的 Server 發起遠程調用。

3. Tars

Tars 是騰訊根據內部多年使用微服務架構的實踐,總結而成的開源項目,僅支持 C++ 語言,它的架構圖如下。

從0開始學微服務:14 開源RPC框架如何選型?

Tars 的架構交互主要包括以下幾個流程:

  • 服務發佈流程:在 web 系統上傳 server 的發佈包到 patch,上傳成功後,在 web 上提交發布 server 請求,由 registry 服務傳達到 node,然後 node 拉取 server 的發佈包到本地,拉起 server 服務。
  • 管理命令流程:web 系統上的可以提交管理 server 服務命令請求,由 registry 服務傳達到 node 服務,然後由 node 向 server 發送管理命令。
  • 心跳上報流程:server 服務運行後,會定期上報心跳到 node,node 然後把服務心跳信息上報到 registry 服務,由 registry 進行統一管理。
  • 信息上報流程:server 服務運行後,會定期上報統計信息到 stat,打印遠程日誌到 log,定期上報屬性信息到 prop、上報異常信息到 notify、從 config 拉取服務配置信息。
  • client 訪問 server 流程:client 可以通過 server 的對象名 Obj 間接訪問 server,client 會從 registry 上拉取 server 的路由信息(如 IP、Port 信息),然後根據具體的業務特性(同步或者異步,TCP 或者 UDP 方式)訪問 server(當然 client 也可以通過 IP/Port 直接訪問 server)。

4. Spring Cloud

Spring Cloud 是為了解決微服務架構中服務治理而提供的一系列功能的開發框架,它是完全基於 Spring Boot 進行開發的,Spring Cloud 利用 Spring Boot 特性整合了開源行業中優秀的組件,整體對外提供了一套在微服務架構中服務治理的解決方案。因為 Spring Boot 是用 Java 語言編寫的,所以目前 Spring Cloud 也只支持 Java 語言平臺,它的架構圖可以用下面這張圖來描述。

從0開始學微服務:14 開源RPC框架如何選型?

由此可見,Spring Cloud 微服務架構是由多個組件一起組成的,各個組件的交互流程如下。

  • 請求統一通過 API 網關 Zuul 來訪問內部服務,先經過 Token 進行安全認證。
  • 通過安全認證後,網關 Zuul 從註冊中心 Eureka 獲取可用服務節點列表。
  • 從可用服務節點中選取一個可用節點,然後把請求分發到這個節點。
  • 整個請求過程中,Hystrix 組件負責處理服務超時熔斷,Turbine 組件負責監控服務間的調用和熔斷相關指標,Sleuth 組件負責調用鏈監控,ELK 負責日誌分析。

5. 對比選型

介紹完這 4 種限定語言的開源 RPC 框架後,我們該如何選擇呢?

很顯然,如果你的語言平臺是 C++,那麼只能選擇 Tars;而如果是 Java 的話,可以選擇 Dubbo、Motan 或者 Spring Cloud。這時你又要問了,它們三個又該如何抉擇呢?

仔細分析,可以看出 Spring Cloud 不僅提供了基本的 RPC 框架功能,還提供了服務註冊組件、配置中心組件、負載均衡組件、斷路器組件、分佈式消息追蹤組件等一系列組件,也難怪被技術圈的人稱之為“Spring Cloud 全家桶”。如果你不想自己實現以上這些功能,那麼 Spring Cloud 基本可以滿足你的全部需求。而 Dubbo、Motan 基本上只提供了最基礎的 RPC 框架的功能,其他微服務組件都需要自己去實現。

不過由於 Spring Cloud 的 RPC 通信採用了 HTTP 協議,相比 Dubbo 和 Motan 所採用的私有協議來說,在高併發的通信場景下,性能相對要差一些,所以對性能有苛刻要求的情況下,可以考慮 Dubbo 和 Motan。

跨語言平臺的開源 RPC 框架

1. gRPC

先來看下 gRPC,它的原理是通過 IDL(Interface Definition Language)文件定義服務接口的參數和返回值類型,然後通過代碼生成程序生成服務端和客戶端的具體實現代碼,這樣在 gRPC 裡,客戶端應用可以像調用本地對象一樣調用另一臺服務器上對應的方法。

從0開始學微服務:14 開源RPC框架如何選型?

它的主要特性包括三個方面。

  • 通信協議採用了 HTTP/2,因為 HTTP/2 提供了連接複用、雙向流、服務器推送、請求優先級、首部壓縮等機制,所以在通信過程中可以節省帶寬、降低 TCP 連接次數、節省 CPU,尤其對於移動端應用來說,可以幫助延長電池壽命。
  • IDL 使用了,ProtoBuf 是由 Google 開發的一種數據序列化協議,它的壓縮和傳輸效率極高,語法也簡單,所以被廣泛應用在數據存儲和通信協議上。
  • 多語言支持,能夠基於多種語言自動生成對應語言的客戶端和服務端的代碼。

2. Thrift

再來看下 Thrift,Thrift 是一種輕量級的跨語言 RPC 通信方案,支持多達 25 種編程語言。為了支持多種語言,跟 gRPC 一樣,Thrift 也有一套自己的接口定義語言 IDL,可以通過代碼生成器,生成各種編程語言的 Client 端和 Server 端的 SDK 代碼,這樣就保證了不同語言之間可以相互通信。它的架構圖可以用下圖來描述。

從0開始學微服務:14 開源RPC框架如何選型?

從這張圖上可以看出 Thrift RPC 框架的特性。

  • 支持多種序列化格式:如 Binary、Compact、JSON、Multiplexed 等。
  • 支持多種通信方式:如 Socket、Framed、File、Memory、zlib 等。
  • 服務端支持多種處理方式:如 Simple 、Thread Pool、Non-Blocking 等。

3. 對比選型

那麼涉及跨語言的服務調用場景,到底該選擇 gRPC 還是 Thrift 呢?

從成熟度上來講,Thrift 因為誕生的時間要早於 gRPC,所以使用的範圍要高於 gRPC,在 HBase、Hadoop、Scribe、Cassandra 等許多開源組件中都得到了廣泛地應用。而且 Thrift 支持多達 25 種語言,這要比 gRPC 支持的語言更多,所以如果遇到 gRPC 不支持的語言場景下,選擇 Thrift 更合適。

但 gRPC 作為後起之秀,因為採用了 HTTP/2 作為通信協議、ProtoBuf 作為數據序列化格式,在移動端設備的應用以及對傳輸帶寬比較敏感的場景下具有很大的優勢,而且開發文檔豐富,根據 ProtoBuf 文件生成的代碼要比 Thrift 更簡潔一些,從使用難易程度上更佔優勢,所以如果使用的語言平臺 gRPC 支持的話,建議還是採用 gRPC 比較好。

總結

以上就是我對幾種使用最廣泛的開源 RPC 框架的選型建議,也是基於它們目前現狀所作出的判斷,從長遠來看,支持多語言是 RPC 框架未來的發展趨勢。正是基於此判斷,各個 RPC 框架都提供了 Sidecar 組件來支持多語言平臺之間的 RPC 調用。

  • Dubbo 在去年年底又重啟了維護,並且宣稱要引入 Sidecar 組件來構建Dubbo Mesh提供多語言支持。
  • Motan 也在去年對外開源了其內部的 Sidecar 組件:Motan-go,目前支持 PHP、Java 語言之間的相互調用。
  • Spring Cloud 也提供了 Sidecar 組件spring-cloud-netflix-sideca,可以讓其他語言也可以使用 Spring Cloud 的組件。

所以未來語言不會成為使用上面這幾種 RPC 框架的約束,而 gRPC 和 Thrift 雖然支持跨語言的 RPC 調用,但是因為它們只提供了最基本的 RPC 框架功能,缺乏一系列配套的服務化組件和服務治理功能的支撐,所以使用它們作為跨語言調用的 RPC 框架,就需要自己考慮註冊中心、熔斷、限流、監控、分佈式追蹤等功能的實現,不過好在大多數功能都有開源實現,可以直接採用。

思考題

同樣是支持跨語言的 RPC 調用,你覺得 gRPC 這類的跨語言服務框架和 Motan-go 這類的 Sidecar 方案有什麼區別?在使用過程中都需要注意什麼?

歡迎你在留言區寫下自己的思考,與我一起討論。


分享到:


相關文章: