0 准备
参考资料
下载gRPC
git clone -b v1.27.0 https://github.com/grpc/grpc
python环境
python virtualenv环境准备
$ python -m pip install virtualenv
$ virtualenv grpc_venv
$ source grpc_venv/Scripts/activate
$ python -m pip install --upgrade pip
在环境中添加如下两个包:
pip install grpcio
pip install grpcio-tools
或者可以全局环境添加
$ sudo python -m pip install grpcio
$ sudo python -m pip install grpcio-tools
或者直接在ide里面添加。
1 编辑.proto文件
文件路径:grpc/examples/protos/route_guide.proto
2. 根据.proto文件生成服务器端和客户端代码
cd grpc/examples/python/route_guide
python -m grpc_tools.protoc -I../../protos --python_out=. --grpc_python_out=. ../../protos/route_guide.proto
这个命令产生如下两个文件:
test_grpc\grpc\examples\python\route_guide\route_guide_pb2_grpc.py
test_grpc\grpc\examples\python\route_guide\route_guide_pb2.py
创建服务器端处理程序
服务器端代码分析
实现RouteGuide
简单RPC代码
def GetFeature(self, request, context):
feature = get_feature(self.db, request)
if feature is None:
return route_guide_pb2.Feature(name="", location=request)
else:
return feature
返回流式RPC代码
def ListFeatures(self, request, context):
left = min(request.lo.longitude, request.hi.longitude)
right = max(request.lo.longitude, request.hi.longitude)
top = max(request.lo.latitude, request.hi.latitude)
bottom = min(request.lo.latitude, request.hi.latitude)
for feature in self.db:
if (feature.location.longitude >= left and
feature.location.longitude <= right and
feature.location.latitude >= bottom and
feature.location.latitude <= top):
yield feature
请求流式RPC代码
def RecordRoute(self, request_iterator, context):
point_count = 0
feature_count = 0
distance = 0.0
prev_point = None
start_time = time.time()
for point in request_iterator:
point_count += 1
if get_feature(self.db, point):
feature_count += 1
if prev_point:
distance += get_distance(prev_point, point)
prev_point = point
elapsed_time = time.time() - start_time
return route_guide_pb2.RouteSummary(point_count=point_count,
feature_count=feature_count,
distance=int(distance),
elapsed_time=int(elapsed_time))
双向流式RPC代码
def RouteChat(self, request_iterator, context):
prev_notes = []
for new_note in request_iterator:
for prev_note in prev_notes:
if prev_note.location == new_note.location:
yield prev_note
prev_notes.append(new_note)
启动服务器代码
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
RouteGuideServicer(), server)
server.add_insecure_port('[::]:50051')
server.start()
创建客户端
客户端代码分析
创建stub
channel = grpc.insecure_channel('localhost:50051')
stub = route_guide_pb2_grpc.RouteGuideStub(channel)
调用服务器方法
对于返回单个响应的RPC方法(“响应一元”方法),gRPC Python支持同步(阻塞)和异步(非阻塞)控制流语义。 对于响应流式RPC方法,调用立即返回响应值的迭代器。 调用该迭代器的next()方法块,直到要从该迭代器产生的响应变为可用为止。
调用简单RPC代码
对简单RPC GetFeature的同步调用几乎与调用本地方法一样简单。 RPC调用等待服务器响应,并且将返回响应或引发异常:
feature = stub.GetFeature(point)
对GetFeature的异步调用与此类似,但是就像在线程池中异步调用本地方法一样:
feature_future = stub.GetFeature.future(point)
feature = feature_future.result()
调用响应流式RPC
for feature in stub.ListFeatures(rectangle):
调用请求流式RPC
调用请求流RecordRoute类似于将迭代器传递给本地方法。就像上面的简单RPC也返回单个响应一样,可以同步或异步调用它:
route_summary = stub.RecordRoute(point_iterator)
route_summary_future = stub.RecordRoute.future(point_iterator)
route_summary = route_summary_future.result()
调用双向流式RPC
调用双向流RouteChat具有服务流和响应流语义的组合(在服务端就是这种情况):
for received_route_note in stub.RouteChat(sent_route_note_iterator):