gRPC - 使用 Python 的 Hello World 应用程序
现在让我们创建一个基本的"Hello World"类应用程序,它将使用 gRPC 和 Python。
.proto 文件
首先让我们在 common_proto_files 中定义 greeting.proto 文件 −
syntax = "proto3"; service Greeter { rpc greet (ClientInput) returns (ServerOutput) {} } message ClientInput { string greeting = 1; string name = 2; } message ServerOutput { string message = 1; }
现在让我们仔细看看上面块 − 中的每一行
syntax = "proto3";
这里的 "syntax" 代表我们正在使用的 Protobuf 版本。因此,我们使用最新版本 3,因此模式可以使用对版本 3 有效的所有语法。
package tutorial;
这里的 package 用于解决冲突,例如,我们有多个同名的类/成员。
service Greeter { rpc greet(ClientInput) returns (ServerOutput) {} }
此块表示服务的名称"Greeter"和可调用的函数名称"greet"。"greet"函数接受类型为"ClientInput"的输入并返回类型为"ServerOutput"的输出。现在让我们看看这些类型。
message ClientInput { string greeting = 1; string name = 2; }
在上面的代码块中,我们定义了 ClientInput,它包含两个属性,即"greeting"和"name",它们都是字符串。客户端应该将"ClientInput"类型的对象发送到服务器。
message ServerOutput { string message = 1; }
这里,我们还定义了,给定一个"ClientInput",服务器将返回具有单个属性"message"的"ServerOutput"。服务器应该将类型为"ServerOutput"的对象发送到客户端。
现在,让我们为 Protobuf 类和 gRPC 类生成底层代码。为此,我们需要执行以下命令 −
python -m grpc_tools.protoc -I ..\common_proto_files\ -- python_out=../python --grpc_python_out=. Greeting.proto
但是,请注意,要执行该命令,我们需要安装正确的依赖项,如本教程的 setup 部分所述。
这应该会自动生成我们使用 gRPC 所需的源代码。源代码将放在 −
Protobuf 类代码:python/greeting_pb2.py Protobuf gRPC 代码:python/greeting_pb2_grpcpb2.py
设置 gRPC 服务器
现在我们已经定义了包含函数定义的 proto 文件,让我们设置一个可以调用这些函数的服务器。
让我们编写服务器代码来提供上述功能并将其保存在 server.py −
示例
from concurrent import futures import grpc import greeting_pb2 import greeting_pb2_grpc class Greeter(greeting_pb2_grpc.GreeterServicer): def greet(self, request, context): print("Got request " + str(request)) return greeting_pb2.ServerOutput(message='{0} {1}!'.format(request.greeting, request.name)) def server(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=2)) greeting_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) server.add_insecure_port('[::]:50051') print("gRPC starting") server.start() server.wait_for_termination() server()
上述代码在指定端口启动一个 gRPC 服务器,并提供我们在 proto 文件中编写的功能和服务。让我们看一下上面的代码 −
从 main 方法开始,我们在指定端口创建一个 gRPC 服务器。
但在启动服务器之前,我们为服务器分配了我们想要运行的服务,即在我们的例子中为 Greeter 服务。
为此,我们需要将服务实例传递给服务器,因此我们继续创建一个服务实例,即在我们的例子中为 Greeter。
服务实例需要提供 .proto 文件中存在的方法/函数的实现,即在我们的例子中为 greet 方法。
该方法需要一个在 .proto 中定义的类型的对象文件,即我们的 request。
该方法对上述输入进行操作,进行计算,然后应该返回 .proto 文件中提到的输出,即我们的例子中的 ServerOutput。
设置 gRPC 客户端
现在我们已经编写了服务器代码,让我们设置一个可以调用这些函数的客户端。
让我们编写客户端代码来调用上述函数并将其保存在 client.py −
示例
import grpc import greeting_pb2 import greeting_pb2_grpc def run(): with grpc.insecure_channel('localhost:50051') as channel: stub = greeting_pb2_grpc.GreeterStub(channel) response = stub.greet(greeting_pb2.ClientInput(name='John', greeting = "Yo")) print("Greeter client received following from server: " + response.message) run()
上述代码在指定端口启动 gRPC 服务器,并提供我们在 proto 文件中编写的功能和服务。让我们来看看上面的代码 −
从 main 方法开始,我们设置了一个用于与服务器进行 gRPC 通信的通道。
然后,我们使用该通道创建一个 stub。在这里我们使用服务"Greeter",我们计划调用其功能。stub 只不过是一个包装器,它向调用者隐藏了远程调用的复杂性。
然后,我们只需创建 proto 文件中定义的预期输入,即我们例子中的 ClientInput。我们已经硬编码了两个参数,即 name 和 greeting。
我们最终进行调用并等待服务器的结果。
所以,这就是我们的客户端代码。
客户端服务器调用
现在,我们已经定义了 proto 文件,编写了服务器和客户端代码,让我们继续执行此代码并查看实际操作。
要运行代码,请启动两个 shell。通过执行以下命令在第一个 shell 上启动服务器 −
python .\server.py
输出
我们将得到以下输出 −
gRPC 正在启动
上述输出表示服务器已启动。
现在,让我们启动客户端。
python .\client.py
我们将看到以下输出 −
输出
Greeter 客户端从服务器收到以下内容:Yo John!
现在,如果我们打开服务器日志,我们将看到以下数据 −
gRPC starting Got request greeting: "Yo" name: "John"
因此,正如我们所见,客户端能够按预期调用服务器,并且服务器响应并向客户端问候。