【问题标题】:How to access the method name in a Python gRPC handler如何在 Python gRPC 处理程序中访问方法名称
【发布时间】:2020-08-01 00:50:57
【问题描述】:

我正在尝试从 gRPC 处理程序中访问方法名称 service/Method。我似乎无法在 grpc.ServicerContext 对象上找到这些数据(而且我很确定它不存在)。我的下一个想法是使用拦截器,因为方法名称是通过grpc.HandlerCallDetails 提供的。问题是没有任何明显的方法可以将此转发给底层处理程序。

不幸的是,grpc.HandlerCallDetails 没有构造函数,因此我们不能将方法名称放入元数据中以便在处理程序中读取。我们必须创建一个命名元组,它与grpc.HandlerCallDetails 的接口相同,并向其中添加一个新的元数据值。

如果有人遇到此问题并有解决方案,或者 grpc 团队中的某个人有解决方法,那就太好了。

此外,这可能会更容易一些,因为此类功能已有现有技术。 grpc-goMethod 名称来帮助解决这个 https://pkg.go.dev/google.golang.org/grpc?tab=doc#Method。在 C++ 中,您似乎可以将其从人口普查上下文中拉出来。

【问题讨论】:

    标签: python grpc grpc-python


    【解决方案1】:

    我认为您找到了正确的组件。 HandlerCallDetails用于让gRPC servicer匹配方法名和handler。

    一种可能的方法是通过实现ServiceRpcHandler。您可以实现自己的处理程序并将其提供给 gRPC 服务器。在服务处理程序中,您可以提供方法名称信息作为第三个参数,或者将其附加到服务上下文,或者分配给线程本地存储。

    此外,ProtoBuf 生成的代码隐藏了这个细节,可以很好地参考它是如何完成的。

    这里是一份 ProtoBuf 生成的代码:

    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,))
    

    这是默认的服务 RPC 处理程序implementation

    class DictionaryGenericHandler(grpc.ServiceRpcHandler):
    
        def __init__(self, service, method_handlers):
            self._name = service
            self._method_handlers = {
                _common.fully_qualified_method(service, method): method_handler
                for method, method_handler in six.iteritems(method_handlers)
            }
    
        def service_name(self):
            return self._name
    
        def service(self, handler_call_details):
            return self._method_handlers.get(handler_call_details.method)
    

    【讨论】:

    • 感谢您的回答,但似乎这种方法需要放弃生成的 protobuf 代码。我的解决方案是使用 metaclasses + abc 强制我的基本 Servicer mixin 的子类手动指定服务名称(通过描述符获取),然后只使用当前 python 方法的名称,因为它与 gRPC 方法名称和然后将它们加入我的装饰器中,该装饰器包装了所有 gRPC 方法。感觉很 hacky,生成的代码应该会让这更容易一些。
    猜你喜欢
    • 2016-02-04
    • 1970-01-01
    • 2016-03-07
    • 2019-03-07
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 2012-12-30
    相关资源
    最近更新 更多