淺談.NET 6 中 gRPC 的最新功能

語言: CN / TW / HK

微軟中國MSDN  點選上方 藍字 關注我們

gRPC   是一個現代的、跨平臺的、高效能的 RPC 框架。gRPC 是構建在 ASP.NET Core 之上,也是我們推薦的使用 .NET 構建 RPC 服務的方法。

.NET 6 進一步提高了 gRPC 已經非常出色的效能,並添加了一系列新功能,使 gRPC 在現代雲原生應用程式中比以往任何時候都更好。在這篇文章中,我將描述這些新功能以及我們如何通過第一個支援端到端 HTTP/3 的 gRPC 實現引領行業。

gPRC 客戶端負載均衡

客戶端負載平衡是一項允許 gRPC 客戶端在可用伺服器之間優化分配負載的功能。客戶端負載平衡可以消除對負載平衡代理的需要。這有幾個好處:

  • 改進的效能 。無代理意味著消除額外的網路躍點並減少延遲,因為 RPC 直接傳送到 gRPC 伺服器。

  • 有效利用伺服器資源 。負載平衡代理必須解析然後重新發送通過它傳送的每個 HTTP 請求。刪除代理可以節省 CPU 和記憶體資源。

  • 更簡單的應用程式架構 。必須正確設定和配置代理伺服器。沒有代理伺服器意味著更少的活動部件!

客戶端負載均衡是在建立通道時配置的。使用負載均衡時要考慮的兩個元件:

  • 解析器,解析通道的地址。解析器支援從外部源獲取地址。這也稱為服務發現。

  • 負載均衡器,它建立連線並選擇 gRPC 呼叫將使用的地址。

以下程式碼示例將通道配置為使用具有迴圈負載平衡的 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" });

更多資訊,請參閱  gPRC 客戶端負載平衡

  • gPRC 

    https://docs.microsoft.com/aspnet/core/grpc/

  • gPRC 客戶端負載平衡:

    https://docs.microsoft.com/aspnet/core/grpc/loadbalancing

帶有重試的瞬間故障處理

gRPC 呼叫可能會被瞬時故障中斷。瞬態故障包括:

  • 網路連線暫時中斷。

  • 服務暫時不可用。

  • 由於伺服器負載超時。

當 gRPC 呼叫被中斷時,客戶端會丟擲一個包含錯誤詳細資訊的 RpcException。客戶端應用程式必須捕獲異常並選擇如何處理錯誤。

var client =newGreeter.GreeterClient(channel);
try
{
    var response =await client.SayHelloAsync(
        newHelloRequest{Name=".NET"});
    Console.WriteLine("From server: "+ response.Message);
}
catch(RpcException ex)
{
    // Write logic to inspect the error and retry
    // if the error is from a transient fault.

}

在整個應用程式中複製重試邏輯是冗長且容易出錯的。幸運的是,.NET gRPC 客戶端現在內建了對自動重試的支援。重試在通道上集中配置,並且有許多選項可用於使用 RetryPolicy 自定義重試行為。

var defaultMethodConfig =newMethodConfig
{
    Names={MethodName.Default},
    RetryPolicy=newRetryPolicy
    {
        MaxAttempts=5,
        InitialBackoff=TimeSpan.FromSeconds(1),
        MaxBackoff=TimeSpan.FromSeconds(5),
        BackoffMultiplier=1.5,
        RetryableStatusCodes={StatusCode.Unavailable}
    }
};
// Clients created with this channel will automatically retry failed calls.
var channel =GrpcChannel.ForAddress("https://localhost:5001",newGrpcChannelOptions
{
    ServiceConfig=newServiceConfig{MethodConfigs={ defaultMethodConfig }}
});

有關更多資訊,請參閱 使用 gRPC 重試進行瞬態故障處理

  • 使用 gPRC 重試進行瞬態故障處理:

    https://docs.microsoft.com/aspnet/core/grpc/retries

Protobuf 效能

關於.NET 的 gRPC 使用 Google.Protobuf 包作為訊息的預設序列化程式。Protobuf 是一種高效的二進位制序列化格式。Google.Protobuf 旨在提高效能,使用程式碼生成而不是反射來序列化 .NET 物件。在 .NET 5 中,我們與 Protobuf 團隊合作,為序列化程式添加了對現代記憶體 API(例如 Span<T>、ReadOnlySequence<T>和IBufferWriter<T>)的支援。.NET 6 中的改進優化了一個已經很快的序列化程式。 

protocolbuffers/protobuf#8147添加了向量化字串序列化。SIMD 指令允許並行處理多個字元,從而在序列化某些字串值時顯著提高效能。

privatestring _value =newstring(' ',10080);
privatebyte[] _outputBuffer =newbyte[10080];
[Benchmark]
publicvoidWriteString()
{
    var span =newSpan<byte>(_outputBuffer);
    WriteContext.Initialize(ref span,outWriteContext 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.UnsafeWrap 來建立一個 ByteString 而不復制底層資料。如果應用程式處理大位元組有效負載並且您想降低垃圾收集頻率,這將非常有用。

  • protocolbuffers/protobuf#7645:

    https://github.com/protocolbuffers/protobuf/pull/7645

gPRC 下載速度

gRPC 使用者報告有時下載速度變慢。我們的調查發現,當客戶端和伺服器之間存在延遲時,HTTP/2 流量控制會限制下載。伺服器在客戶端可以耗盡之前填充接收緩衝區視窗,導致伺服器暫停傳送資料。gRPC 訊息以開始/停止突發方式下載。

這已在 dotnet/runtime#54755 中修復。HttpClient 現在動態縮放接收緩衝區視窗。建立HTTP/2 連線後,客戶端將向伺服器傳送 ping 以測量延遲。如果存在高延遲,客戶端會自動增加接收緩衝區視窗,從而實現快速、連續的下載。

privateGrpcChannel _channel =GrpcChannel.ForAddress(...);
privateDownloadClient _client =newDownloadClient(_channel);
[Benchmark]
publicTaskGrpcLargeDownload()=>

_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

  • dotnet/runtime#54755

    https://github.com/dotnet/runtime/pull/54755

HTTP/3 支援

NET 上的 gRPC 現在支援 HTTP/3。gRPC 建立在 .NET 6 中新增到 ASP.NET Core 和 HttpClient 的 HTTP/3 支援之上。有關更多資訊,請參閱 .NET 6 中的 HTTP/3 支援。

.NET 是第一個支援端到端 HTTP/3 的 gRPC 實現,我們已經為其他平臺 提交了 gRFC ,以便將來支援 HTTP/3。帶有 HTTP/3 的 gRPC 是 開發人員社群高度要求的功能 ,很高興看到 .NET 在該領域處於領先地位。

  • .NET 6 中的 HTTP/3 :

    https://devblogs.microsoft.com/dotnet/http-3-support-in-dotnet-6/

  • gRFC:

    https://github.com/grpc/proposal/pull/256

  • 開發人員社群高度要求的功能:

    https://github.com/grpc/grpc/issues/19126

總結

效能是 .NET gRPC 的一個特性,而 .NET 6 比以往任何時候都快。客戶端負載平衡和 HTTP/3 等以效能為導向的新功能意味著更低的延遲、更高的吞吐量和更少的伺服器。這是一個節省資金、減少能耗和 構建更環保的雲原生應用程式 的機會。

要試用新功能並開始在 .NET 中使用 gRPC ,最好的起點是在 ASP.NET Core 教程中建立 gRPC 客戶端和伺服器。

我們期待聽到有關使用 gRPC .NET 構建的應用程式以及您   dotnet   和  grpc   儲存庫中的貢獻!

  • 構建更環保的雲原生應用程式 :

    https://docs.microsoft.com/aspnet/core/tutorials/grpc/grpc-start

  • dotnet:

    https://github.com/dotnet

  • grpc:

    https://github.com/grpc

.NET 上的 gRPC參考文件