文章目录
工具要求
- ubuntu20.04
- Python 3.5 或更高版本
- pip 9.0.1 或更高版本
安装grpc
python -m pip install grpcio
安装grpc工具
python -m pip install grpcio-tools
下载示例代码
git clone -b v1.42.0 https://github.com/grpc/grpc
文件结构分析
- helloworld.proto:定义服务
- (自动生成)hello_pb2.py:包含我们生成的请求和响应类
- (自动生成)hello_pb2_grpc.py:包含我们生成的客户端和服务器类的内容,调用了hello_pb2.py
- greeter_server.py:服务器
- greeter_client.py:客户端
helloworld.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
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;
}
python -m grpc_tools.protoc -I…/…/protos –python_out=. –grpc_python_out=. …/…/protos/helloworld.proto
分别是helloworld.proto所在的文件夹路径,生成pb2、pb2_grpc文件的路径,helloworld.proto的完整路径。
helloworld_pb2_grpc.py
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import helloworld_pb2 as helloworld__pb2
class GreeterStub(object):
"""The greeting service definition.
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.SayHello = channel.unary_unary(
'/helloworld.Greeter/SayHello',
request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
response_deserializer=helloworld__pb2.HelloReply.FromString,
)
class GreeterServicer(object):
"""The greeting service definition.
"""
def SayHello(self, request, context):
"""Sends a greeting
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_GreeterServicer_to_server(servicer, server):
rpc_method_handlers = {
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello,
request_deserializer=helloworld__pb2.HelloRequest.FromString,
response_serializer=helloworld__pb2.HelloReply.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'helloworld.Greeter', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class Greeter(object):
"""The greeting service definition.
"""
@staticmethod
def SayHello(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/helloworld.Greeter/SayHello',
helloworld__pb2.HelloRequest.SerializeToString,
helloworld__pb2.HelloReply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
类图:
关键全局函数:
add_GreeterServicer_to_server(servicer, server)
greeter_server.py
"""The Python implementation of the GRPC helloworld.Greeter server."""
from concurrent import futures
import logging
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) #返回结果,使用到了pb2
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
logging.basicConfig()
serve()
关键全局函数:
serve()
greeter_client.py
from __future__ import print_function
import logging
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
def run():
channel = grpc.insecure_channel('localhost:50051')
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you')) #关键,发送request,使用到了pb2
print("Greeter client received: " + response.message)
if __name__ == '__main__':
logging.basicConfig()
run()
基本通信流程
greeter_client.py调用stub.SayHello(helloworld_pb2.HelloRequest(name=‘you’)),向server发送请求,传到了greeter_server.py中的Greeter中的SayHello(),执行return helloworld_pb2.HelloReply(message=‘Hello, %s!’ % request.name),此时stub.SayHello()函数返回,response得到结果。
问题:helloworld_pb2.HelloRequest()函数和helloworld_pb2.HelloReply()函数?
回顾helloworld.proto:
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
操作①实际上是:helloworld_pb2_grpc.py中GreeterStub类的SayHello()函数:channel.unary_unary(
‘/helloworld.Greeter/SayHello’,
request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
response_deserializer=helloworld__pb2.HelloReply.FromString,
)
操作②是:greeter_server中的Greeter类的SayHello()函数,该类继承于helloworld_pb2_grpc.py中的GreeterServicer类。