一.什么是RPC
1.簡介:
RPC:Remote Procedure Call,遠程過程調用。簡單來說就是兩個進程之間的數據交互。
正常服務端的接口服務是提供給用戶端(在Web開發中就是瀏覽器)或者自身調用的,也就是本地過程調用。
和本地過程調用相對的就是:假如兩個服務端不在一個進程內怎么進行數據交互?使用RPC。
尤其是現在微服務的大量實踐,服務與服務之間的調用不可避免,RPC更顯得尤為重要。
2.原理:
計算機的世界中不管使用哪種技術,核心都是對數據的操作。RPC不過是將數據的操作垮了一個維度而已。
解決的問題本質上只是數據在不同進程間的傳輸。我們所說的RPC一般是指在傳輸層使用TCP協議進行的數據交互,
也有很多基於HTTP的成熟框架。
gRPC調用如下圖所示:
上圖描述了一個RPC的完整調用流程: 1:client向client stub發起方法調用請求。 2:client stub接收到請求后,將方法名,請求參數等信息進行編碼序列化。 3:client stub通過配置的ip和端口使用socket通過網絡向遠程服務器server發起請求。 4:遠程服務器server接收到請求,解碼反序列化請求信息。 5:server將請求信息交給server stub,server stub找到對應的本地真實方法實現。 6:本地方法處理調用請求並將返回的數據交給server stub。 7:server stub 將數據編碼序列化交給操作系統內核,使用socket將數據返回。 8:client端socket接收到遠程服務器的返回信息。 9:client stub將信息進行解碼反序列化。 10:client收到遠程服務器返回的信息。
上圖中有一個stub(存根)的概念。
stub負責接收本地方法調用,並將它們委托給各自的具體實現對象。
server端stub又被稱為skeleton(骨架)。可以理解為代理類。而實際上基於Java的RPC框架stub基本上也都是使用動態代理。
我們所說的client端和server端在RPC中一般也都是相對的概念。
而所謂的RPC框架也就是封裝了上述流程中2-9的過程,讓開發者調用遠程方法就像調用本地方法一樣。
二.常用的RPC框架選型
-
Dubbo:
阿里開源的基於TCP的RPC框架,基本上是國內生產環境應用最廣的開發框架了。使用zookeeper做服務的注冊與發現,使用Netty做網絡通信。遺憾的是不能跨語言,目前只支持Java。
-
Thrift:
Facebook開源的跨語言的RPC框架,通過IDL來定義RPC的接口和數據類型,使用thrift編譯器生成不同語言的實現。據說是目前性能最好的RPC框架,只是暫沒使用過。
-
gRPC:
這個是我們今天要聊的重點。gRPC是Google的開源產品,是跨語言的通用型RPC框架,使用Go語言編寫。 Java語言的應用同樣使用了Netty做網絡通信,Go采用了Goroutine做網絡通信。序列化方式采用了Google自己開源的Protobuf。請求的調用和返回使用HTTP2的Stream。
-
SpringCloud:
SpringCloud並不能算一個RPC框架,它是Spring家族中一個微服務治理的解決方案,是一系列框架的集合。但在這個方案中,微服務之間的通信使用基於HTTP的Restful API,使用Eureka或Consul做服務注冊與發現,使用聲明式客戶端Feign做服務的遠程調用。這一系列的功能整合起來構成了一套完整的遠程服務調用。
如何選擇
如果公司項目使用Java並不牽扯到跨語言,且規模並沒有大到難以治理,我推薦Dubbo。如果項目規模大,服務調用錯綜復雜,我推薦SpringCloud。
如果牽扯到跨語言,我推薦gRPC,這也是目前我司的選擇。即使Thrift性能是gRPC的2倍,但沒辦法,它有個好爹,現在我們的開發環境考慮最多的還是生態,不得不向Google爸爸臣服。
三.gRPC原理
一個RPC框架必須有兩個基礎的組成部分:數據的序列化和進程數據通信的交互方式。
對於序列化gRPC采用了自家公司開源的Protobuf。什么是Protobuf?先看一句網絡上 大部分的解釋:
Google Protocol Buffer(簡稱 Protobuf)是一種輕便高效的結構化數據存儲格式,平台無關、語言無關、可擴展,可用於通訊協議和數據存儲等領域。
上句有幾個關鍵點:它是一種數據存儲格式,跨語言,跨平台,用於通訊協議和數據存儲。
這么看和我們熟悉的JSON類似,但其實着重點有些本質的區別:
JSON主要是用於數據的傳輸,因為它輕量級,可讀性好,解析簡單。
Protobuf主要是用於跨語言的IDL,它除了和JSON、XML一樣能定義結構體之外,還可以使用自描述格式定於出接口的特性,
並可以使用針對不同語言的protocol編譯器產生不同語言的stub類。所以天然的適用於跨語言的RPC框架中。
而關於進程間的通訊,無疑是Socket。Java方面gRPC同樣使用了成熟的開源框架Netty。使用Netty Channel作為數據通道。傳輸協議使用了HTTP2。
通過以上的分析,我們可以將一個完整的gRPC流程總結為以下幾步:
- 通過.proto文件定義傳輸的接口和消息體。
- 通過protocol編譯器生成server端和client端的stub程序。
- 將請求封裝成HTTP2的Stream。
- 通過Channel作為數據通信通道使用Socket進行數據傳輸。
四.gRPC的簡單實現
項目需求:
go調用java傳遞請求參數,並接收java返回的數據。(項目中本人采用http方式建立go&java連接)
為了體現gRPC跨語言的特性,我們使用兩種語言:Go實現server端,Java作為client端來實現
1。安裝Protocol Buffers,定義.proto文件
Step1:登錄Google的 github下載對應Protocol Buffers版本 (本人下載all)
Step2:安裝Protocol Buffer
// Step1:安裝 Protocol Buffer 依賴 // 注:Protocol Buffer 依賴於 autoconf、automake、libtool、curl brew install autoconf automake libtool curl // Step2:進入 Protocol Buffer安裝包 解壓后的文件夾(我的解壓文件放在桌面) cd Desktop/protobuf-3.6.1 // Step3:運行 autogen.sh 腳本 ./autogen.sh // Step4:運行 configure.sh 腳本 ./configure // Step5:編譯未編譯的依賴包 make // Step6:檢查依賴包是否完整 make check // Step7:開始安裝Protocol Buffer make install
Step3:檢查Protocol Buffer是否安裝成功
// 在 終端 下輸入 protoc - - version
執行protoc命令如果返回如下信息說明安裝成功
未完待緒。。。。