gpt4 book ai didi

c# - C# 中的 gRPC 压缩

转载 作者:行者123 更新时间:2023-11-30 16:41:27 27 4
gpt4 key购买 nike

使用 C# 时是否可以控制 gRPC 中的响应消息压缩?

This question收到评论但没有答复。评论指向 gRPC issue #10902其中说:

The functionality is there, but you need to unable [enable?] by setting appropriate channel option or by setting a metadata entry in your RPC.



test class链接那里显示了一些可能性:
new WriteOptions(WriteFlags.NoCompress)

但这对我没有影响:无论此设置如何,WAN 上的调用都需要相同的时间。
var compressionMetadata = new Metadata
{
{ new Metadata.Entry(Metadata.CompressionRequestAlgorithmMetadataKey, "gzip") }
};

同样,测试显示更改此设置时调用时间没有变化。 ( CompressionRequestAlgorithmMetadataKey 常量是内部的,我反编译得到字符串值)。

有一个诱人的 CompressionLevel枚举 in the C# github repo但我找不到它的任何用法。

gRPC issue #4170 (在 C# 中实现压缩支持)已关闭,但表示

It can be done in C#, but it's definitely not user friendly



有没有人能帮我举个例子来说明如何做到这一点?如果它不是用户友好的,我不介意,我只是希望能够做到!我正在通过网络发送一些大的(~8Mb)响应,我想对它们进行一些控制。虽然我可以在发送之前压缩数据,但允许客户端对使用的方法/压缩级别进行一些控制会很好。

(我会发布一些代码,但我只是使用来自 C# sample code 的测试代码和一个大的硬编码字符串)

tl;dr 我不知道如何使用 C# gRPC 控制压缩设置。所有看起来可能的设置都不会影响通过线路发送响应所花费的时间。



编辑
在 Jon Skeet 关于查看有线流量的评论之后,我运行了一个新测试,其中响应是字符串 The quick brown fox jumps over the lazy dog重复 5000 次。我通过以下方式打开了 gRPC 跟踪
        Environment.SetEnvironmentVariable("GRPC_TRACE", "compression");
Environment.SetEnvironmentVariable("GRPC_VERBOSITY", "DEBUG");
GrpcEnvironment.SetLogger(new ConsoleLogger());

...在客户端和服务器上。我使用 Wireshark 捕获网络流量,解码我的 gRPC 服务器端口上的 HTTP2 流量。

测试 #1:没有控制压缩的特定代码
  • 可以看到流量没有被压缩。

  • 测试 #2:服务器关闭压缩
  • 套装context.WriteOptions = new WriteOptions(WriteFlags.NoCompress);在返回响应之前在服务器端。
  • 可以看到流量没有被压缩。

  • 测试 #3:服务器启用压缩
  • 套装context.ResponseTrailers.Add(new Metadata.Entry("grpc-internal-encoding-request", "gzip"));在返回响应之前在服务器端。
  • 可以看到流量没有被压缩。

  • 测试 #4:客户端启用压缩
  • 调用服务器时设置元数据头:var headers = new Metadata {{new Metadata.Entry("grpc-internal-encoding-request", "gzip")}};
  • 客户端 gRPC 跟踪记录以下

  • D0228 16:53:21.566026 0 C:\jenkins\workspace\gRPC_build_artifacts\platform\windows\workspace_csharp_ext_windows_x64\src\core\ext\filters\http\message_compress\message_compress_filter.cc:262: Algorithm 'gzip' enabled but decided not to compress. Input size: 0


  • 我认为这是试图压缩请求而不是响应?
  • 可以看到流量没有被压缩。




  • 编辑 #2
    Jan Tattermusch 明白这一点。在我的服务器端方法中添加此代码
            var headers = new Metadata{new Metadata.Entry("grpc-internal-encoding-request", "gzip")};            
    await context.WriteResponseHeadersAsync(headers);

    ……成功了! Wireshark 显示响应被压缩并显示 gRPC 日志

    Compressed[gzip] 225002 bytes vs. 742 bytes (99.67% savings)



    杰出的!可悲的是,它导致了我的下一个问题:压缩的开销导致此方法调用比未压缩的数据慢!
    更多的谷歌搜索让我找到了更好的选择:创建 Server 时您可以传递一个集合 ChannelOption 的对象s。我设置如下:
    var options = new[] {new ChannelOption("grpc.default_compression_level", (int) CompressionLevel.Low)};

    这将压缩设置为更好的级别(对于我在此处发送的数据),并且具有启用 gzip 压缩作为所有调用的默认值的副作用。现在每个方法都必须明确关闭压缩(通过我的测试 #2 中的 WriteOptions)。

    有趣的是,尝试通过 grpc-internal-encoding-request 覆盖默认压缩现在非常慢,我猜是由于引发了异常:

    src\core\lib\surface\call.cc:1018: prepare_application_metadata: {"created":"@1520008670.738000000","description":"Unallowed duplicate metadata","file":"C:\jenkins\workspace\gRPC_build_artifacts\platform\windows\workspace_csharp_ext_windows_x64\src\core\lib\transport\metadata_batch.cc","file_line":111,"key":"grpc-internal-encoding-request","value":"gzip"}



    这意味着我不能在每次调用的基础上修改和更改压缩算法或级别,但考虑到打开压缩后的性能优势,我是一个快乐的人。

    最佳答案

    测试 #1 和测试 #2 似乎按预期运行。

    测试#3:

  • AFAIK grpc C# 目前不支持在服务器端启用压缩
  • 您尝试在服务器端使用的 header “grpc-internal-encoding-request”元数据 header 只能用于客户端
  • 您正在将 header 添加到 context.ResponseTrailers.Add() - 响应预告片在所有响应都已传输后由服务器发送,因此无论如何这都没有机会工作。如果支持设置压缩,则需要将 header 添加到 context.ResponseHeaders() 中。

  • 测试#4:
  • 我相信你在做什么(=设置“grpc-internal-encoding-request”)是正确的,看起来你正在发送一个大小为0的请求,所以grpc决定没有压缩的意义(有一个大小压缩不会启动的阈值)。
  • 关于c# - C# 中的 gRPC 压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49031763/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com