本篇博文完整讲述了如果通过 protocol buffers 定义并启动一个 gRPC 服务,然后在 gRPC 服务上提供一个 RESTful JSON API 的反向代理 gateway,最后通过 swagger ui 来提供 RESTful JSON API 的说明,完整代码 helloworld_restful_swagger。
Helloworld gRPC Service参考 gRPC Quick Start for Python。
Install gRPC 安装 gRPC运行命令,
$ python -m pip install grpcio
安装 gRPC 工具箱Python 的 gRPC 工具箱包括 protol buffer 编译器 protoc 和一些特定插件用于从 .proto 服务定义文件生成 gRPC server 和 client 的代码。
运行命令,
$ python -m pip install grpcio-tools
服务定义文件 helloworld.proto在 pb 目录下新建文件 helloworld.proto,然后在其中使用 protocol buffers 语法来编写 gRPC 服务定义。文件内容如下:
syntax = "proto3"; package helloworld; // 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; }
protoc 编译生成 server 和 client 类定义使用下面命令来生成 gRPC 的 server 和 client 类定义代码文件,
$ python -m grpc.tools.protoc -I. --python_out=. --grpc_python_out=. pb/helloworld.proto
命令没有报错的话,将会在 pb 目录下生成两个文件 helloworld_pb2.py 和 helloworld_pb2_grpc.py。
其中文件 helloworld_pb2.py 包含了 HelloRequest 和 HelloReploy 的消息类定义,而文件 helloworld_pb2_grpc.py 提供了 gRPC server 类(GreeterServicer)和 client 类(GreeterStub)定义。
编写具体的 gRPC 服务类文件 helloworld_pb2_grpc.py 提供了 gRPC server 类(GreeterServicer)提供了 gRPC 服务的规范定义,没有具体的实现。我们需要自己编写 gRPC 服务类文件 server.py,代码如下,
from concurrent import futures import time import grpc import pb.helloworld_pb2 as pb_dot_helloworld__pb2 import pb.helloworld_pb2_grpc as pb_dot_helloworld_pb2__grpc _ONE_DAY_IN_SECONDS = 60 * 60 * 24 class MyServer(pb_dot_helloworld_pb2__grpc.GreeterServicer): def SayHello(self, request, context): print("Receive request, request.name: {0}".format(request.name)) return pb_dot_helloworld__pb2.HelloReply( message=‘Hello, {0}‘.format(request.name)) def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) pb_dot_helloworld_pb2__grpc.add_GreeterServicer_to_server(MyServer(), server) server.add_insecure_port(‘[::]:50051‘) print("GreeterServicer start at port 50051...") server.start() try: while True: time.sleep(_ONE_DAY_IN_SECONDS) except KeyboardInterrupt: server.stop(0) if __name__ == ‘__main__‘: serve()
然后启动 gRPC server,
$ python server.py lienhuadeMacBook-Pro:helloworld_restful_swagger lienhua34$ python server.py GreeterServicer start at port 50051...
编写 gRPC client.py文件 helloworld_pb2_grpc.py 提供了 gRPC client 类(GreeterStub)定义。我们需要编写自己的 client.py 代码来通过 GreeterStub 调用 gRPC server 方法。代码内容如下:
import grpc import pb.helloworld_pb2 as pb_dot_helloworld__pb2 import pb.helloworld_pb2_grpc as pb_dot_helloworld_pb2__grpc def run(): channel = grpc.insecure_channel(‘localhost:50051‘) stub = pb_dot_helloworld_pb2__grpc.GreeterStub(channel) response = stub.SayHello(pb_dot_helloworld__pb2.HelloRequest(name="world")) print("GreeterService client received: " + response.message) if __name__ == ‘__main__‘: run()
运行 client.py 代码,
lienhuadeMacBook-Pro:helloworld_restful_swagger lienhua34$ python client.py GreeterService client received: Hello, world
至此,可见我们的 gRPC helloworld 服务已经可用。
RESTful JSON API Gateway调用 gRPC 服务需要自己编写相对应的 client 代码才行,这无疑给访问 gRPC 带来了一定的难度。我们可以通过在 gRPC 服务上面提供一个 RESTful API gateway,可以直接通过 RESTful JSON API 来访问。
grpc-gateway 是 protoc 的一个插件,,用于读取 gRPC 服务定义,然后生成一个反向代理服务来将 RESTful JSON API 转换为 gRPC 调用。
Install grpc-gateway确保你本地安装了 golang 6.0 以上版本,并且将 $GOPATH/bin 添加到 $PATH 中。然后运行下面命令,