「譯」 .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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM