Я пытаюсь реализовать клиент и сервер gRPC, используя реализацию Python gRPC в качестве ссылки.
Согласно спецификации в https://github.com/grpc/grpc/blob/master/doc/compression.md есть несколько вариантов использования, которые должны поддерживаться:
Сжатие МОЖЕТ быть настроено клиентским приложением путем вызова
соответствующий метод API. Есть два сценария, где сжатие МОЖЕТ
быть настроенным:
- Во время создания канала, который устанавливает сжатие канала по умолчанию
и, следовательно, сжатие, которое ДОЛЖНО использоваться в отсутствие
конфигурация сжатия для каждого RPC.
- Во время ответа, через: Для одинарного
RPC, экземпляр контекста {Client, Server}. Для потоковых RPC
Экземпляр {Client, Server} Writer. В этом случае конфигурация уменьшается
отключить сжатие в целом.
...
Асимметрия метода сжатия между пирами
Узел gRPC МОЖЕТ выбрать
ответить, используя другой метод сжатия, чем в запросе,
в том числе не выполняет никакого сжатия, независимо от канала и
Настройки RPC (например, если сжатие приведет к небольшому или
отрицательный прирост).
...
Специальное отключение сжатия
Если пользователь (через ранее
описанные механизмы) запросы на отключение сжатия следующего сообщения
ДОЛЖЕН быть отправлен без сжатия. Это способствует предотвращению
Зверь / Преступление атаки. Это касается как унарного, так и потокового
случаи.
Некоторые из них кажутся возможными, а другие нет. Решая их один за другим, я думаю, что это возможно:
- Во время создания канала, который устанавливает сжатие канала по умолчанию
и, следовательно, сжатие, которое ДОЛЖНО использоваться в отсутствие
конфигурация сжатия для каждого RPC.
Это работает. На сервере вы можете указать:
from grpc._cython.cygrpc import CompressionAlgorithm, CompressionLevel
server_options = [(
"grpc.default_compression_algorithm", CompressionAlgorithm.gzip
),(
"grpc.default_compression_level", CompressionLevel.high
)]
server = grpc.server(
futures.ThreadPoolExecutor(max_workers=10), options=server_options
)
А на клиенте:
from grpc._cython.cygrpc import CompressionAlgorithm
channel_options = [(
"grpc.default_compression_algorithm", CompressionAlgorithm.gzip
)]
channel = grpc.insecure_channel(
"127.0.0.1:{}".format(port), options=channel_options
)
Это правильно устанавливает алгоритмы по умолчанию с обеих сторон.
Вы можете переопределить алгоритм сжатия для конкретного вызова, установив ключ метаданных grpc-internal-encoding-request
:
stub.MethodName(request, metadata={'grpc-internal-encoding-request': 'gzip'})
Это в конечном итоге устанавливает заголовок grpc-encoding
для запроса, и тело кодируется соответствующим образом.
Пока все хорошо. Далее:
Асимметрия метода сжатия между пирами
Узел gRPC МОЖЕТ выбрать
ответить, используя другой метод сжатия, чем в запросе,
в том числе не выполняет никакого сжатия, независимо от канала и
Настройки RPC
Я нашел пример того, как это сделать, в этом модульном тесте и справочном вопросе переполнения стека . Однако, когда я пытаюсь сделать это, я вижу ошибку в моих журналах, и заголовок ответа не изменяется:
prepare_application_metadata: {"created":"@1541795237.323499000","description":"Unallowed duplicate metadata","file":"src/core/lib/transport/metadata_batch.cc","file_line":113,"key":"grpc-internal-encoding-request","value":"gzip"}
Ошибка возникает, когда на сервере также установлен алгоритм сжатия по умолчанию . Когда нет значения по умолчанию, оно работает.
Соответственно, принятый ответ на этот вопрос о переполнении стека предполагает, что grpc-internal-encoding-request
следует использовать только в клиенте (что имеет смысл, учитывая имя)
Так что я не знаю, есть ли ошибка, из-за которой вы не можете установить значение по умолчанию и переопределение одновременно, или же настройка grpc-internal-encoding-request
действительно недействительна на стороне сервера (и если да, то как кодировка ответа) следует изменить)
Наконец:
Специальное отключение сжатия
Если пользователь (через ранее
описанные механизмы) запросы на отключение сжатия следующего сообщения
ДОЛЖЕН быть отправлен без сжатия. Это способствует предотвращению
Зверь / Преступление атаки. Это касается как унарного, так и потокового
случаи.
Эта проблема Github говорит о том, что это поддерживается, но, похоже, только заглушки клиента в пакете beta
, даже несмотря на то, что ссылочная фиксация была объединена в 2015 году. Поддерживается ли эта поддержка в некоторых случаях? вроде дорожной карты, или я что-то пропустил?
У меня нет , чтобы использовать реализацию Python для справки. Есть ли более полная реализация на другом языке?