Как получить доступ к имени метода в обработчике Python gRP C - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь получить доступ к имени метода service/Method из обработчика gRP C. Кажется, я не могу найти эти данные на объекте grpc.ServicerContext (и я почти уверен, что их там нет). Следующей моей мыслью было использовать перехватчик, поскольку имя метода передается через grpc.HandlerCallDetails. Проблема в том, что нет очевидного способа передать это базовому обработчику.

К сожалению, grpc.HandlerCallDetails не имеет конструктора, поэтому мы не можем взять имя метода и вставить его в метаданные для чтения в обработчике. Нам нужно было бы создать именованный кортеж с тем же интерфейсом, что и grpc.HandlerCallDetails, и добавить к нему новое значение метаданных.

Было бы здорово, если бы кто-нибудь столкнулся с этим и нашел решение, или если бы кто-то У команды grp c есть обходной путь.

Вдобавок, вероятно, это должно быть что-то более простое, поскольку для такого рода функций уже есть предшествующий уровень техники. grpc-go имеет имя Method, чтобы помочь с этим https://pkg.go.dev/google.golang.org/grpc?tab=doc#Method. Похоже, что в C ++ вы потенциально можете вытащить это из контекста переписи.

1 Ответ

0 голосов
/ 04 августа 2020

Думаю, вы нашли нужный компонент. HandlerCallDetails используется, чтобы позволить серверу gRP C соответствовать имени метода и обработчику.

Один из возможных способов сделать это - реализовать ServiceRpcHandler . Вы можете реализовать свой собственный обработчик и передать его серверу gRP C. В обработчике службы вы можете предоставить информацию об имени метода в качестве третьего аргумента, или присоединить ее к контексту службы, или назначить локальному хранилищу потока.

Кроме того, созданный 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,))

Вот сервис RP по умолчанию C обработчик реализация :

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