Как создать GRP C клиент напрямую из protobuf, не компилируя его в java код - PullRequest
0 голосов
/ 10 апреля 2020

При работе с GRP C нам необходимо сгенерировать клиентский и серверный интерфейсы gRP C из нашего определения сервиса .proto через буферный компилятор протокола (proto c) или с использованием Gradle или Maven proto c build Плагин.

Flow now: protobuf file -> java code -> gRPC client.

Итак, есть ли способ пропустить этот шаг?

Как создать универсальный c GRP C клиент, который может вызывать сервер напрямую из protobuf файл без компиляции в java код? Или, есть ли способ сгенерированного кода во время выполнения?

Flow expect: protobuf file -> gRPC client.

Я хочу построить общую клиентскую систему c gRP C с входными данными как файлы protobuf вместе с описанием метода, пакета, запрос сообщения ... без необходимости повторной компиляции для каждого протобуфа.

Большое спасибо.

Ответы [ 3 ]

0 голосов
/ 10 апреля 2020

Технически не так много, чтобы предотвратить это . Два больших препятствия:

  1. с вызываемым во время выполнения анализатором для чтения .proto и
  2. с доступным клиентом общего назначения gRP C, который принимает такие вещи, как служба имя метода в виде литералов

Возможно и то, и другое, но ни одно из них не является тривиальным.

Для 1 грубым способом было бы выполнить shell / invoke protoc, используя опцию descriptor-set для создать двоичный файл схемы, а затем десериализовать его как FileDescriptorSet (из descriptor.proto); эта модель дает вам доступ к тому, как protoc видит файл. Некоторые платформы также имеют собственные синтаксические анализаторы (по существу, переопределяющие protoc как библиотеку на этой платформе), например, protobuf- net .Reflection делает это в. NET -land

Для 2 вот реализация этого в C#. Подход должен быть достаточно переносимым на Java, даже если детали различаются. Вы можете посмотреть на сгенерированную реализацию, чтобы увидеть, как она работает на любом конкретном языке.

(Извините, что указанные примеры c - это C # /. NET, но там я живу; Подходы должны быть переносимыми, даже если указанный c код: не напрямую)

0 голосов
/ 10 апреля 2020

Системы Protobuf действительно нуждаются в прото c для запуска. Однако сгенерированный код может быть пропущен. Вместо того, чтобы передавать что-то вроде --java_out и --grpc_java_out в proto c, вы можете передать --descriptor_set_out=FILE, который будет анализировать файл .proto в файл дескриптор . Файл дескриптора является прото-закодированным FileDescriptorSet. Это тот же базовый формат c, который используется со службой отражения.

Получив дескриптор, вы можете загрузить его FileDescriptor за один раз и создать DynamicMessage .

Затем для части gRP C необходимо создать дескриптор метода gRP C.

MethodDescriptor.<DynamicMessage, DynamicMessage>newBuilder()
    // UNKNOWN is fine, but the "correct" value can be computed from
    // methodDesc.toProto().getClientStreaming()/getServerStreaming()
    .setType(MethodDescriptor.MethodType.UNKNOWN)
    .setFullMethodName(MethodDescriptor.generateFullMethodName(
        serviceDesc.getFullName(), methodDesc.getName()))
    .setRequestMarshaller(ProtoUtils.marshaller(
        DynamicMessage.newBuilder(methodDesc.getInputType()).buildPartial()))
    .setResponseMarshaller(ProtoUtils.marshaller(
        DynamicMessage.newBuilder(methodDesc.getOutputType()).buildPartial()))
    .build();

В этот момент у вас есть все, что вам нужно, и вы можете позвонить Channel.newCall(method, CallOptions.DEFAULT) в гП C. Вы также можете использовать ClientCalls для использования чего-то более похожего на API-заглушки.

Так что динамические вызовы c безусловно возможны и используются для таких вещей, как grpcurl . Но это также нелегко, и, как правило, это делается только при необходимости.

0 голосов
/ 10 апреля 2020

технически оба возможны.

Codegen просто генерирует несколько классов; в основном сообщения protobuf, дескрипторы и заглушки метода grp c. Вы можете реализовать это или проверить в сгенерированном коде, чтобы обойти кодеген. Я не уверен, в чем выгода от этого. Кроме того, это будет очень раздражать, если прототип будет изменен.

Возможно также сделать это динамически, используя байт-коден, пока вы регистрируете некоторые интерфейсы / абстрактные классы для представления этих сгенерированных дескрипторов заглушки / метода. и протобуф сообщения. Вы должны убедиться, что этот не динамический код c находится в синхронизации c с определением прототипа (скорее всего, проверка / исключение во время выполнения).

...