.NET 6 中 gRPC 的新功能
gRPC是一個(gè)現(xiàn)代的、跨平臺的、高性能的 RPC 框架。gRPC for .NET 構(gòu)建在 ASP.NET Core 之上,是我們推薦的在 .NET 中構(gòu)建 RPC 服務(wù)的方法。
.NET 6 進(jìn)一步提高了 gRPC 已經(jīng)非常出色的性能,并添加了一系列新功能,使 gRPC 在現(xiàn)代云原生應(yīng)用程序中比以往任何時(shí)候都更好。在這篇文章中,我將描述這些新功能, 以及我們?nèi)绾瓮ㄟ^第一個(gè)支持端到端 HTTP/3 的 gRPC 實(shí)現(xiàn)引領(lǐng)行業(yè)。
gRPC 客戶端負(fù)載均衡
客戶端負(fù)載均衡功能允許 gRPC 客戶端以最佳方式在可用服務(wù)器之間分配負(fù)載, 這樣就不需要使用專門的負(fù)載均衡代理服務(wù)器, 這有幾個(gè)好處:
?性能改進(jìn), 無代理可以減少網(wǎng)絡(luò)延遲, 因?yàn)?RPC 直接發(fā)送到 gRPC 服務(wù)器, 無需中轉(zhuǎn)。
?節(jié)省服務(wù)器資源,負(fù)載平衡代理必須解析然后重新發(fā)送每個(gè) HTTP 請求, 本身也會(huì)占用 CPU 和內(nèi)存, 所以移除代理可以節(jié)省服務(wù)器資源。
?更簡單的程序架構(gòu), gRPC 負(fù)載均衡代理需要安裝, 配置才能正常工作, 而使用客戶端負(fù)載均衡, 客戶端直接發(fā)送到服務(wù)端, 程序的架構(gòu)也很簡單。
如果要使用客戶端負(fù)載均衡, 需要在創(chuàng)建 channel 的時(shí)候進(jìn)行配置, 另外使用負(fù)載均衡時(shí)要考慮兩個(gè)組件
?resolver 解析器, 它可以從創(chuàng)建的 channel 中返回服務(wù)地址, 并且支持從外部源獲取地址, 其實(shí)這就是我們熟悉的服務(wù)發(fā)現(xiàn)。
?load balancer 負(fù)載均衡器, 當(dāng)調(diào)用 gRPC 的時(shí)候, 它會(huì)根據(jù)配置的負(fù)載均衡的策略, 返回響應(yīng)的服務(wù)地址, 并創(chuàng)建連接。
下面的代碼中, 給 GrpcChannel 配置了 DNS 服務(wù)發(fā)現(xiàn)和輪詢的負(fù)載均衡策略。
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" });有關(guān)更多信息,請參考?gRPC 客戶端負(fù)載平衡[1]。
瞬時(shí)故障的處理和重試
gRPC 調(diào)用過程中可能會(huì)遇到瞬時(shí)故障而中斷,瞬時(shí)故障包括:
?網(wǎng)絡(luò)連接暫時(shí)中斷。?服務(wù)暫時(shí)不可用。?服務(wù)器響應(yīng)超時(shí)。
當(dāng) gRPC 調(diào)用中斷時(shí),客戶端會(huì)拋出?RpcException?有關(guān)錯(cuò)誤的詳細(xì)信息,客戶端應(yīng)用程序需要捕獲異常并選擇如何處理錯(cuò)誤,如下
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){ // 這里記錄錯(cuò)誤并重試}在您的程序中, 你可能需要在很多地方寫這樣的處理代碼, 幸運(yùn)的是,.NET gRPC 客戶端現(xiàn)在內(nèi)置了對自動(dòng)重試的支持, 只需要在 channel 上統(tǒng)一配置即可, 并且支持幾種不同的重試策略。
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 } }};// 發(fā)生錯(cuò)誤時(shí)可以自動(dòng)重試var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions{ ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }});有關(guān)更多信息,請參閱使用?gRPC 重試進(jìn)行瞬態(tài)故障處理[2]。
Protobuf 性能
gRPC for .NET 使用 Google.Protobuf 庫作為消息的默認(rèn)序列化程序。Protobuf 是一種高效的二進(jìn)制序列化格式。Google.Protobuf 旨在提高性能,使用代碼生成而不是反射來序列化 .NET 對象。在.NET 5,我們和 Protobuf 團(tuán)隊(duì)合作并支持了內(nèi)存API的序列化, 包括?Span<T>, ReadOnlySequence<T>, IBufferWriter<T>?, 在.NET 6, 序列化的性能得到進(jìn)一步的優(yōu)化和提升。
protocolbuffers/protobuf#8147[3]?支持了矢量化字符串的序列化。SIMD 指令允許并行處理多個(gè)字符,從而在序列化某些字符串值時(shí)顯著提高性能。
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[4]?添加了一個(gè)用于創(chuàng)建?ByteString?實(shí)例的新 API,?UnsafeByteOperations.UnsafeWrapByteString, 如果您知道底層數(shù)據(jù)不會(huì)發(fā)生改變, 那么可以使用它創(chuàng)建, 這樣如果應(yīng)用程序處理大字節(jié)數(shù)據(jù)時(shí)并且您想降低垃圾收集的頻率,這將非常有用。
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 用戶反映有時(shí)下載速度會(huì)變慢, 特別時(shí)較大的文件, 我們的調(diào)查發(fā)現(xiàn),當(dāng)內(nèi)容大于初始的接收窗口大小時(shí),并且客戶端和服務(wù)器之間存在高延遲, 會(huì)導(dǎo)致網(wǎng)絡(luò)阻塞和整體吞吐量降低。
這已在?dotnet/runtime#54755[5]?中修復(fù)。HttpClient 現(xiàn)在動(dòng)態(tài)縮放接收緩沖區(qū)窗口。建立 HTTP/2 連接后,客戶端將向服務(wù)器發(fā)送 ping 以測量延遲。如果存在高延遲,客戶端會(huì)自動(dòng)增加接收緩沖區(qū)窗口,從而實(shí)現(xiàn)快速、連續(xù)的下載。
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 現(xiàn)在支持 HTTP/3, 其中在 .NET 6 的 ASP.NET Core 和 HttpClient, 有關(guān)更多信息,請參閱?.NET 6 中的 HTTP/3 支持[6]。
.NET 是第一個(gè)支持端到端 HTTP/3 的 gRPC 實(shí)現(xiàn),我們已經(jīng)為其他平臺提交了?gRFC[7],以便將來支持 HTTP/3。帶有 HTTP/3 的 gRPC 是開發(fā)人員社區(qū)高度要求的功能[8],很高興看到 .NET 在該領(lǐng)域處于領(lǐng)先地位。
總結(jié)
性能是 .NET 和 gRPC 的一個(gè)重要特性,而 .NET 6 比以往任何時(shí)候都快。客戶端負(fù)載均衡和 HTTP/3 等以性能為導(dǎo)向的新功能意味著更低的延遲、更高的吞吐量和更少的服務(wù)器。這是一個(gè)節(jié)省資金、減少能耗和構(gòu)建更環(huán)保的云原生應(yīng)用程序的機(jī)會(huì)。
要試用新功能并開始在 .NET 中使用 gRPC,最好的起點(diǎn)是在 ASP.NET Core教程中?創(chuàng)建 gRPC 客戶端和服務(wù)器[9]。
我們期待聽到有關(guān)使用 gRPC 和 .NET 構(gòu)建的應(yīng)用程序以及您未來在dotnet和grpc 存儲庫中的貢獻(xiàn)!
作者: James Newton-King?
原文: https://devblogs.microsoft.com/dotnet/grpc-in-dotnet-6/
相關(guān)鏈接
[1]?gRPC 客戶端負(fù)載平衡:?https://docs.microsoft.com/zh-cn/aspnet/core/grpc/loadbalancing?view=aspnetcore-6.0
[2]?gRPC 重試進(jìn)行瞬態(tài)故障處理:?https://docs.microsoft.com/zh-cn/aspnet/core/grpc/retries?view=aspnetcore-6.0
[3]?protocolbuffers/protobuf#8147:?https://github.com/protocolbuffers/protobuf/pull/8147
[4]?protocolbuffers/protobuf#7645:?https://github.com/protocolbuffers/protobuf/pull/7645
[5]?dotnet/runtime#54755:?https://github.com/protocolbuffers/protobuf/pull/7645
[6]?.NET 6 中的 HTTP/3 支持:?https://devblogs.microsoft.com/dotnet/http-3-support-in-dotnet-6/
[7]?gRFC:?https://github.com/grpc/proposal/pull/256
[8]?開發(fā)人員社區(qū)高度要求的功能:?https://github.com/grpc/grpc/issues/19126
[9]?創(chuàng)建 gRPC 客戶端和服務(wù)器:?https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-6.0&tabs=visual-studio
總結(jié)
以上是生活随笔為你收集整理的.NET 6 中 gRPC 的新功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSharp 如何OCR离线识别文本
- 下一篇: WPF学习笔记(二):初学者避坑实录