gRPC:由 Google 开发的一个高性能、开源和通用性强的 RPC 框架

动机
我们 Node 项目的后端请求没有直接使用 HTTP 模块,而是采用了 gRPC on Node.js(@grpc/grpc-js),而之前没有接触过。
概念
学一个东西最快的方式,就是先找个 DEMO 跑起来(我已经找到了),直接感受下。不过 gPRC 属实有点复杂,我们还是要从几个简单的概念开始认识。
gRPC
是 Google RPC 的简写,是 Google 基于 RPC 开发的一个通信框架(相当于是 PRC 一个实现方), 也是一套通用的通信方案。因此,gRPC 是语言无关的,并不限制是用哪个语言(比如:JavaScript(Node 平台) 、Java 等),你可以在官网《Supported languages》里看到 gRPC 支持的语言,并跟随里面的例子,快速开始。
RPC
全称是“Remote Procedure Call”,即“远程过程调用”,是一种远程通信模型,这个模型定义了一个计算机程序在不同的地址空间中,如何调用另外一个地址空间的子程序或函数。
RPC 中并没有规定使用何种通信协议传输数据,既可以使用 HTTP,也可以使用 TCP、UDP、HTTP2。像 gRPC 内部就是使用 HTTP2 这个 HTTP 协议的最新版本实现数据传输的。
Protocol Buffers
Protocol Buffers 简称 ProtoBuf,跟 JSON 一样,就是一种数据格式,官方叫“序列化协议”,存储这种数据格式的文件使用的是 .proto
后缀。它是由 Google 开发的,与相对于数据格式协议(如 XML 和 JSON 等)一样,与平台、语言无关,不过更小、更快。
在 gRPC 中,Protocol Buffers 被用作 IDL(Interface Definition Language,接口定义语言)使用(目前使用最新的第 3 版居多,又称“proto 3”),所以你会看到一个个服务都是在一个个 .proto
文件中定义的。
最后要说的是,相对于在 Node 端直接使用 HTTP 模块,从使用感受上,RPC 对开发者而言,更像是是一个本地调用,而不是远程调用。
快速开始
我们这里的快速开始教程,基于官方 Node 端教程和仓库代码(grpc/grpc-node)内容整合而成,学有余力的同学读完后也可以自己看看。
下载 example
运行 gPRC 应用
程序运行后,我们会在控制台看到“Greeting: Hello world”的消息输出。
至此,我们就成功运行起来了一个 gPRC 应用 了。
增加一个新的 gRPC 服务方法
现在,我们修改下服务,增加一个调用方法供客户端消费。查看 greeter_server.js 文件,会看到以下代码:
这里 helloworld.proto
就是定义服务接口的地方,使用 Protocol Buffers 数据格式定义;helloworld.proto
文件接口都定义在了 helloworld
这个命名空间下了。
现在打开 grpc-node/examples/protos/helloworld.proto
文件:
目前,我们只要知道服务器和客户端“stub”都定义了一个 SayHello
的 RPC 方法,这个方法从客户端接收一个 HelloRequest
类型的参数,并从服务器返回一个 HelloReply
类型的响应。
我们更新一下,给 Greeter
服务增加一个新的 SayHelloAgain
方法,请求和响应类型与之前相同:
保存文件!
更新并运行程序
我们加了一个新的服务定义,但是没有具体实现,这块实现代码需要我们人工编写。打开 greeter_server.js
文件,在 main()
方法内部增加 sayHelloAgain
方法实现:
我们照葫芦(sayHello
)画瓢(sayHelloAgain
),完成 sayHelloAgain
服务方法的代码实现。
更新客户端
在同一个目录中,打开 greeter_client.js
文件,像这样调用新的方法:
在客户端,我们增加了调用 sayHelloAgain
服务的代码,然后打印响应数据。
运行!
再一次运行我们的项目代码:
多了一个 “Greeting: Hello again,world”输出,我们的修改完成!
增加拦截器
gRPC 还支持客户端拦截器的添加。在客户端调用服务时,可以在携带参数之后,跟上选项参数(options),其中支持通过 interceptors 参数,传入一个由拦截器函数组成的一个数组。
logger
拦截器的定义如下:
拦截器内部提供了 start
、sendMessage
、halfClose
、ca
这些涉及请求周期范围内的钩子函数。另外 start
钩子函数内部,还提供 onReceiveMessage
、onReceiveStatus
钩子函数,针对响应数据的过程进行干预。在这些钩子函数中,通过 next()
函数将请求传递给下一个拦截器处理
进一步了解
如果想要进一步了解项目文件代码的含义,可以参考官方《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