我正在尝试使用Python gRPC实现作为参考来实现gRPC客户端和服务器。
根据https://github.com/grpc/grpc/blob/master/doc/compression.md上的规范文档,应支持几种用例:
压缩可以由客户端应用程序通过调用 适当的API方法。在两种情况下,压缩可能 配置:
- 在创建频道时设置频道默认压缩 因此在没有以下情况的情况下应使用的压缩 每个RPC压缩配置。
- 在响应时,通过:对于一元 RPC,{Client,Server} Context实例。对于流式RPC, {Client,Server} Writer实例。在这种情况下,配置会减少 完全禁用压缩。
...
同伴之间的压缩方法不对称
一个gRPC对等端可以选择 使用与请求不同的压缩方法进行响应, 包括不执行任何压缩,无论通道和 RPC设置(例如,如果压缩会导致压缩或压缩 负收益)。
...
特定的压缩禁用
如果用户(通过之前的 描述的机制)请求禁用下一条消息的压缩 必须未压缩地发送。这有助于防止 BEAST / CRIME攻击。一元和流媒体都适用 案例。
其中一些似乎可行,而其他则不可行。逐一解决它们,这是我认为可能的方法:
- 在创建频道时设置频道默认压缩 因此在没有以下情况的情况下应使用的压缩 每个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设置
在此unit test和引用stack overflow question中,我找到了如何执行此操作的示例。但是,当我尝试执行此操作时,我在日志中看到错误,并且响应标头未更改:
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"}
如果服务器还设置了 default 压缩算法,则会引发错误。没有默认设置时,它似乎可以正常工作。
相关地,对于this stackoverflow question的接受的答案表明grpc-internal-encoding-request
仅应在客户端中使用(给定名称,这是有意义的)
因此,我不知道是否存在无法同时设置默认值和替代值的错误,或者在服务器端设置grpc-internal-encoding-request
是否真的无效(如果这样,响应编码应更改)
最后:
特定的压缩禁用
如果用户(通过之前的 描述的机制)请求禁用下一条消息的压缩 必须未压缩地发送。这有助于防止 BEAST / CRIME攻击。一元和流媒体都适用 案例。
This Github issue表示支持此功能,但是即使引用的提交已在2015年合并,beta
软件包中的客户端存根也似乎支持此功能。是否仍对此提供支持路线图,还是我错过了某个地方的东西?
我没有使用Python实现作为参考。是否有另一种语言的更完整的实现?