» gRPC快速入门:Python » 4. 创建 server » 4.1 实现 RouteGuide

实现 RouteGuide

首先让我们看看如何创建一个 RouteGuide 服务器。

RouteGuide 服务有两个主要部分:

  • 实现从我们的服务定义生成的 servicer 接口:执行我们服务的实际“工作”。
  • 运行 gRPC 服务器以侦听来自客户端的请求并传输响应。

你可以在 examples/python/route_guide/route_guide_server.py 中找到示例 RouteGuide 服务器代码。

让我们拆解一下它是如何工作的。

route_guide_server.py 有一个 RouteGuideServicer 类。它继承自生成的类 route_guide_pb2_grpc.RouteGuideServicer

# RouteGuideServicer 实现 RouteGuide 服务的方法。
class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):

RouteGuideServicer 实现了 RouteGuide 服务所有的方法。

简单 RPC

让我们首先看看最简单的类型,GetFeature。它从客户端获取一个 Point,并返回其数据库中对应的要素信息 Feature

def GetFeature(self, request, context):
    feature = get_feature(self.db, request)
    if feature is None:
        return route_guide_pb2.Feature(name="", location=request)
    return feature

该方法接收一个用于 RPC 的 route_guide_pb2.Point 请求对象,和一个用于提供 RPC 特定的超时限制等信息的 grpc.ServicerContext 对象。 它返回一个 route_guide_pb2.Feature 响应。

服务端流式 RPC

ListFeatures 是一个服务端流式 RPC,或者叫响应流式 RPC。它向客户端发送多个 Feature

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

这里有个 route_guide_pb2.Rectangle 请求 message 用于在其中查找 Feature。相较于返回单个响应,这里 yield(生成)零个或多个响应。

客户端流式 RPC

客户端流式方法 RecordRoute 使用请求值的迭代器并返回单个响应值。

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

最后,让我们看看双向流式 RPC RouteChat

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)

该方法的语义是服务端流式和客户端流式的结合。它接收一个请求值的迭代器并返回一个响应值的迭代器。