概述
我们来看 google 对于 gRPC 的定义:
A high performance, open-source universal RPC framework
即 gRPC 是一个开源的高性能通过 RPC 框架。具体来说,它具有以下特点:
- 使用 protocol buffers 来作为序列化和反序列化,以及接口定义语言 (IDL)
- 跨语言,跨平台,gRPC支持多种平台和多种语言,这应该是 gRPC 框架最大的优势
- 易于使用,安装编译环境和运行环境
- 基于 HTTP/2 ,提供双向传输和认证机制
对于 gRPC 的应用场景,google 给出了一些常见的应用情景,个人则认为更适合于内部服务的使用。
关于 protobuf,多说一下。gRPC 将服务接口的定义写在 .proto
文件中,.proto
文件遵循 protobuf 的规范。使用 gRPC 提供的命令行工具,可以对 .proto
文件进行编译成相关语言的源代码,例如 c++ 语言或者 python 语言的服务端和客户端代码 。
安装
以 python 版本的 gRPC 为例,说明 gRPC 的安装。
1) 将 pip 的版本升级到最新版本
pip install --upgrade pip
2)安装 grpcio 包
pip install grpcio
3)安装 gRPC 的 python 工具包
pip install grpcio-tools
4)下载 gRPC 的官方例子
git clone https://github.com/grpc/grpc
cd grpc/examples/python/helloworld
下载的例子在 gPRC 源代码的 examples 目录中。
使用
环境已安装完毕,接下来便可以运行代码了。进入 examples/python/helloworld
目录。
运行服务端程序,服务端监听 50051端口。
python greeter_server.py
打开另一个终端,运行客户端程序,
python greeter_client.py
可以看到客户端程序的输出
Greeter client received: Hello, you!
说明客户端通过 gRPC 成功从服务端获取了数据。
分析
正常使用 gRPC 的流程是,我们需要首先编写接口和消息的声明文件 .proto
,然后进行编译才可以得到相应接口和消息的源文件。上面我们省略了编译的操作,是由于 gRPC 的源代码中已经将 examples 目录下的例子都编译好了。
打开 examples/protos/helloworld.proto
,可以看到原来的接口和消息声明为:
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
该.proto
文件包括两部分的声明,分别是接口的声明和消息的声明。原来已经有一个接口 SayHello
,假设现在我们需要增加一个接口 SayHelloAgain
,新接口的参数和返回值使用原有的类型,那么新的 .proto
文件如下:
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
// Sends another greeting
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
编写或者更新 .proto
文件后,需要对其进行编译。上面我们安装了 grpcio-tools
工具,可以对 .proto
文件编译。
cd examples/python/helloworld
python -m grpc_tools.protoc -I../../protos --python_out=. --grpc_python_out=. ../../protos/helloworld.proto
执行命令后会生成新的 helloworld_pb2.py
文件和新的 helloworld_pb2_grpc.py
文件。helloworld_pb2.py
文件包含生成的请求类和响应类,而 helloworld_pb2_grpc.py
文件则包含生成的服务端骨架(skeleton)代码和客户端桩(stub)代码。
为了使用新的接口 SayHelloAgain
,需要在我们的程序代码增加新的测试代码。
服务端程序:
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
def SayHelloAgain(self, request, context):
return helloworld_pb2.HelloReply(message='Hello again, %s!' % request.name)
客户端程序:
def run():
channel = grpc.insecure_channel('localhost:50051')
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + response.message)
response = stub.SayHelloAgain(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + response.message)
最后我们再次执行新的服务端和客户端程序。可以看到,客户端终端中,增加了一行输出:
Greeter client received: Hello, you!
Greeter client received: Hello again, you!
说明我们成功添加了新的接口。