zoukankan      html  css  js  c++  java
  • 「译」 .NET 6 中 gRPC 的新功能

    gRPC是一个现代的、跨平台的、高性能的 RPC 框架。gRPC for .NET 构建在 ASP.NET Core 之上,是我们推荐的在 .NET 中构建 RPC 服务的方法。

    .NET 6 进一步提高了 gRPC 已经非常出色的性能,并添加了一系列新功能,使 gRPC 在现代云原生应用程序中比以往任何时候都更好。在这篇文章中,我将描述这些新功能, 以及我们如何通过第一个支持端到端 HTTP/3 的 gRPC 实现引领行业。

    gRPC 客户端负载均衡

    客户端负载均衡功能允许 gRPC 客户端以最佳方式在可用服务器之间分配负载, 这样就不需要使用专门的负载均衡代理服务器, 这有几个好处:

    • 性能改进, 无代理可以减少网络延迟, 因为 RPC 直接发送到 gRPC 服务器, 无需中转。

    • 节省服务器资源,负载均衡代理必须解析然后重新发送每个 HTTP 请求, 本身也会占用 CPU 和内存, 所以移除代理可以节省服务器资源。

    • 更简单的程序架构, gRPC 负载均衡代理需要安装, 配置才能正常工作, 而使用客户端负载均衡, 客户端直接发送到服务端, 程序的架构也很简单。

    如果要使用客户端负载均衡, 需要在创建 channel 的时候进行配置, 另外使用负载均衡时要考虑两个组件

    • resolver 解析器, 它可以从创建的 channel 中返回服务地址, 并且支持从外部源获取地址, 其实这就是我们熟悉的服务发现。

    • load balancer 负载均衡器, 当调用 gRPC 的时候, 它会根据配置的负载均衡的策略, 返回响应的服务地址, 并创建连接。

    下面的代码中, 给 GrpcChannel 配置了 DNS 服务发现和轮询的负载均衡策略。

    var channel = GrpcChannel.ForAddress(
        "dns:///my-example-host",
        new GrpcChannelOptions
        {
            Credentials = ChannelCredentials.Insecure,
            ServiceConfig = new ServiceConfig { LoadBalancingConfigs = { new RoundRobinConfig() } }
        });
    var client = new Greet.GreeterClient(channel);
    
    var response = await client.SayHelloAsync(new HelloRequest { Name = "world" });
    

    有关更多信息,请参考 gRPC 客户端负载均衡

    瞬时故障的处理和重试

    gRPC 调用过程中可能会遇到瞬时故障而中断,瞬时故障包括:

    • 网络连接暂时中断。
    • 服务暂时不可用。
    • 服务器响应超时。

    当 gRPC 调用中断时,客户端会抛出 RpcException 有关错误的详细信息,客户端应用程序需要捕获异常并选择如何处理错误,如下

    var client = new Greeter.GreeterClient(channel);
    try
    {
        var response = await client.SayHelloAsync(
            new HelloRequest { Name = ".NET" });
    
        Console.WriteLine("From server: " + response.Message);
    }
    catch (RpcException ex)
    {
        // 这里记录错误并重试
    }
    

    在您的程序中, 你可能需要在很多地方写这样的处理代码, 幸运的是,.NET gRPC 客户端现在内置了对自动重试的支持, 只需要在 channel 上统一配置即可, 并且支持几种不同的重试策略。

    var defaultMethodConfig = new MethodConfig
    {
        Names = { MethodName.Default },
        RetryPolicy = new RetryPolicy
        {
            MaxAttempts = 5,
            InitialBackoff = TimeSpan.FromSeconds(1),
            MaxBackoff = TimeSpan.FromSeconds(5),
            BackoffMultiplier = 1.5,
            RetryableStatusCodes = { StatusCode.Unavailable }
        }
    };
    
    // 发生错误时可以自动重试
    var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
    {
        ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
    });
    
    

    有关更多信息,请参阅使用 gRPC 重试进行瞬态故障处理

    Protobuf 性能

    gRPC for .NET 使用 Google.Protobuf 库作为消息的默认序列化程序。Protobuf 是一种高效的二进制序列化格式。Google.Protobuf 旨在提高性能,使用代码生成而不是反射来序列化 .NET 对象。在.NET 5,我们和 Protobuf 团队合作并支持了内存API的序列化, 包括 Span<T>, ReadOnlySequence<T>, IBufferWriter<T> , 在.NET 6, 序列化的性能得到进一步的优化和提升。

    protocolbuffers/protobuf#8147 支持了矢量化字符串的序列化。SIMD 指令允许并行处理多个字符,从而在序列化某些字符串值时显著提高性能。

    private string _value = new string(' ', 10080);
    private byte[] _outputBuffer = new byte[10080];
    
    [Benchmark]
    public void WriteString()
    {
        var span = new Span<byte>(_outputBuffer);
        WriteContext.Initialize(ref span, out WriteContext ctx);
        ctx.WriteString(_value);
        ctx.Flush();
    }
    
    Method Google.Protobuf Mean Ratio Allocated
    WriteString 3.14 8.838 us 1.00 0 B
    WriteString 3.18 2.919 ns 0.33 0 B

    protocolbuffers/protobuf#7645 添加了一个用于创建 ByteString 实例的新 API, UnsafeByteOperations.UnsafeWrapByteString, 如果您知道底层数据不会发生改变, 那么可以使用它创建, 这样如果应用程序处理大字节数据时并且您想降低垃圾收集的频率,这将非常有用。

    var data = await File.ReadAllBytesAsync(@"c:large_file.json");
    
    // Safe but slow.
    var copied = ByteString.CopyFrom(data);
    
    // Unsafe but fast. Useful if you know data won't change.
    var wrapped = UnsafeByteOperations.UnsafeWrap(data);
    

    gRPC 下载速度

    gRPC 用户反映有时下载速度会变慢, 特别时较大的文件, 我们的调查发现,当内容大于初始的接收窗口大小时,并且客户端和服务器之间存在高延迟, 会导致网络阻塞和整体吞吐量降低。

    这已在 dotnet/runtime#54755 中修复。HttpClient 现在动态缩放接收缓冲区窗口。建立 HTTP/2 连接后,客户端将向服务器发送 ping 以测量延迟。如果存在高延迟,客户端会自动增加接收缓冲区窗口,从而实现快速、连续的下载。

    private GrpcChannel _channel = GrpcChannel.ForAddress(...);
    private DownloadClient _client = new DownloadClient(_channel);
    
    [Benchmark]
    public Task GrpcLargeDownload() =>
        _client.DownloadLargeMessageAsync(new EmptyMessage());
    
    Method Runtime Mean Ratio
    GrpcLargeDownload .NET 5.0 6.33 s 1.00
    GrpcLargeDownload .NET 6.0 1.65 s 0.26

    HTTP/3 支持

    .NET 上的 gRPC 现在支持 HTTP/3, 其中在 .NET 6 的 ASP.NET Core 和 HttpClient, 有关更多信息,请参阅 .NET 6 中的 HTTP/3 支持

    .NET 是第一个支持端到端 HTTP/3 的 gRPC 实现,我们已经为其他平台提交了 gRFC,以便将来支持 HTTP/3。带有 HTTP/3 的 gRPC 是开发人员社区高度要求的功能,很高兴看到 .NET 在该领域处于领先地位。

    总结

    性能是 .NET 和 gRPC 的一个重要特性,而 .NET 6 比以往任何时候都快。客户端负载均衡和 HTTP/3 等以性能为导向的新功能意味着更低的延迟、更高的吞吐量和更少的服务器。这是一个节省资金、减少能耗和构建更环保的云原生应用程序的机会。

    要试用新功能并开始在 .NET 中使用 gRPC,最好的起点是在 ASP.NET Core教程中 创建 gRPC 客户端和服务器

    我们期待听到有关使用 gRPC 和 .NET 构建的应用程序以及您未来在dotnet和grpc 存储库中的贡献!

    作者: James Newton-King (.NET 首席软件工程师)
    原文: https://devblogs.microsoft.com/dotnet/grpc-in-dotnet-6/

  • 相关阅读:
    PCA算法的最小平方误差解释
    windows下面安装Python和pip终极教程
    理解C/C++的复杂声明
    C++的特殊预处理定义#、##和#@
    虚拟机中linux系统无法打开原保存的显示器配置解决方法
    Visual C++内存泄露检测—VLD工具使用说明
    C++重载、覆盖与隐藏——转载
    python爬虫实战(二)--------千图网高清图
    Linux常用命令12
    Linux常用命令11
  • 原文地址:https://www.cnblogs.com/myshowtime/p/15666336.html
Copyright © 2011-2022 走看看