gRPC:由 Google 開發(fā)的一個(gè)高性能、開源和通用性強(qiáng)的 RPC 框架

動(dòng)機(jī)
我們 Node 項(xiàng)目的后端請求沒有直接使用 HTTP 模塊,而是采用了 gRPC on Node.js(@grpc/grpc-js),而之前沒有接觸過。
概念
學(xué)一個(gè)東西最快的方式,就是先找個(gè) DEMO 跑起來(我已經(jīng)找到了),直接感受下。不過 gPRC 屬實(shí)有點(diǎn)復(fù)雜,我們還是要從幾個(gè)簡單的概念開始認(rèn)識(shí)。
gRPC
是 Google RPC 的簡寫,是 Google 基于 RPC 開發(fā)的一個(gè)通信框架(相當(dāng)于是 PRC 一個(gè)實(shí)現(xiàn)方), 也是一套通用的通信方案。因此,gRPC 是語言無關(guān)的,并不限制是用哪個(gè)語言(比如:JavaScript(Node 平臺(tái)) 、Java 等),你可以在官網(wǎng)《Supported languages》里看到 gRPC 支持的語言,并跟隨里面的例子,快速開始。
RPC
全稱是“Remote Procedure Call”,即“遠(yuǎn)程過程調(diào)用”,是一種遠(yuǎn)程通信模型,這個(gè)模型定義了一個(gè)計(jì)算機(jī)程序在不同的地址空間中,如何調(diào)用另外一個(gè)地址空間的子程序或函數(shù)。
RPC 中并沒有規(guī)定使用何種通信協(xié)議傳輸數(shù)據(jù),既可以使用 HTTP,也可以使用 TCP、UDP、HTTP2。像 gRPC 內(nèi)部就是使用 HTTP2 這個(gè) HTTP 協(xié)議的最新版本實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)?/strong>。
Protocol Buffers
Protocol Buffers 簡稱 ProtoBuf,跟 JSON 一樣,就是一種數(shù)據(jù)格式,官方叫“序列化協(xié)議”,存儲(chǔ)這種數(shù)據(jù)格式的文件使用的是 .proto
后綴。它是由 Google 開發(fā)的,與相對于數(shù)據(jù)格式協(xié)議(如 XML 和 JSON 等)一樣,與平臺(tái)、語言無關(guān),不過更小、更快。
在 gRPC 中,Protocol Buffers 被用作 IDL(Interface Definition Language,接口定義語言)使用(目前使用最新的第 3 版居多,又稱“proto 3”),所以你會(huì)看到一個(gè)個(gè)服務(wù)都是在一個(gè)個(gè) .proto
文件中定義的。
最后要說的是,相對于在 Node 端直接使用 HTTP 模塊,從使用感受上,RPC 對開發(fā)者而言,更像是是一個(gè)本地調(diào)用,而不是遠(yuǎn)程調(diào)用。
快速開始
我們這里的快速開始教程,基于官方 Node 端教程和倉庫代碼(grpc/grpc-node)內(nèi)容整合而成,學(xué)有余力的同學(xué)讀完后也可以自己看看。
下載 example?
運(yùn)行 gPRC 應(yīng)用
程序運(yùn)行后,我們會(huì)在控制臺(tái)看到“Greeting: Hello world”的消息輸出。
至此,我們就成功運(yùn)行起來了一個(gè) gPRC 應(yīng)用 了。
增加一個(gè)新的 gRPC 服務(wù)方法
現(xiàn)在,我們修改下服務(wù),增加一個(gè)調(diào)用方法供客戶端消費(fèi)。查看 greeter_server.js 文件,會(huì)看到以下代碼:
這里 helloworld.proto
就是定義服務(wù)接口的地方,使用 Protocol Buffers 數(shù)據(jù)格式定義;helloworld.proto
文件接口都定義在了 helloworld
這個(gè)命名空間下了。
現(xiàn)在打開 grpc-node/examples/protos/helloworld.proto
文件:
目前,我們只要知道服務(wù)器和客戶端“stub”都定義了一個(gè) SayHello
的 RPC 方法,這個(gè)方法從客戶端接收一個(gè) HelloRequest
類型的參數(shù),并從服務(wù)器返回一個(gè) HelloReply
類型的響應(yīng)。
?
我們更新一下,給 Greeter
服務(wù)增加一個(gè)新的 SayHelloAgain
方法,請求和響應(yīng)類型與之前相同:
保存文件!
更新并運(yùn)行程序
我們加了一個(gè)新的服務(wù)定義,但是沒有具體實(shí)現(xiàn),這塊實(shí)現(xiàn)代碼需要我們?nèi)斯ぞ帉?。打開 greeter_server.js
文件,在 main()
方法內(nèi)部增加 sayHelloAgain
方法實(shí)現(xiàn):
我們照葫蘆(sayHello
)畫瓢(sayHelloAgain
),完成 sayHelloAgain
服務(wù)方法的代碼實(shí)現(xiàn)。
更新客戶端
在同一個(gè)目錄中,打開 greeter_client.js
文件,像這樣調(diào)用新的方法:
在客戶端,我們增加了調(diào)用 sayHelloAgain
服務(wù)的代碼,然后打印響應(yīng)數(shù)據(jù)。
運(yùn)行!
再一次運(yùn)行我們的項(xiàng)目代碼:
多了一個(gè) “Greeting: Hello again,world”輸出,我們的修改完成!
增加攔截器
gRPC 還支持客戶端攔截器的添加。在客戶端調(diào)用服務(wù)時(shí),可以在攜帶參數(shù)之后,跟上選項(xiàng)參數(shù)(options),其中支持通過 interceptors 參數(shù),傳入一個(gè)由攔截器函數(shù)組成的一個(gè)數(shù)組。
logger
攔截器的定義如下:
攔截器內(nèi)部提供了 start
、sendMessage
、halfClose
、ca
這些涉及請求周期范圍內(nèi)的鉤子函數(shù)。另外 start
鉤子函數(shù)內(nèi)部,還提供 onReceiveMessage
、onReceiveStatus
鉤子函數(shù),針對響應(yīng)數(shù)據(jù)的過程進(jìn)行干預(yù)。在這些鉤子函數(shù)中,通過 next()
函數(shù)將請求傳遞給下一個(gè)攔截器處理
進(jìn)一步了解
如果想要進(jìn)一步了解項(xiàng)目文件代碼的含義,可以參考官方《Basics tutorial》(https://grpc.io/docs/languages/node/basics/)教程。
參考資料
https://grpc.io/docs/languages/node/basics/
https://protobuf.dev/overview/
https://protobuf.dev/programming-guides/proto3