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",
newGrpcChannelOptions
{
Credentials = ChannelCredentials.Insecure,
ServiceConfig = newServiceConfig {LoadBalancingConfigs = { newRoundRobinConfig() } }
});
var client = newGreet.GreeterClient(channel);
var response = await client.SayHelloAsync(newHelloRequest { Name = “world”});
更多信息,请参阅 gPRC 客户端负载平衡。
带有重试的霎时故障解决
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 重试进行瞬态故障解决。
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();
}
protocolbuffers/protobuf#7645 增加了一个用于创立 ByteString 实例的新 API。如果你晓得底层数据不会扭转,那么应用 UnsafeByteOperations.UnsafeWrap 来创立一个 ByteString 而不复制底层数据。如果利用程序处理大字节无效负载并且您想升高垃圾收集频率,这将十分有用。
gPRC 下载速度
gRPC 用户报告有时下载速度变慢。咱们的考察发现,当客户端和服务器之间存在提早时,HTTP/2 流量管制会限度下载。服务器在客户端能够耗尽之前填充接收缓冲区窗口,导致服务器暂停发送数据。gRPC 音讯以开始 / 进行突发形式下载。
这已在 dotnet/runtime#54755 中修复。HttpClient 当初动静缩放接收缓冲区窗口。建设 HTTP/2 连贯后,客户端将向服务器发送 ping 以测量提早。如果存在高提早,客户端会主动减少接收缓冲区窗口,从而实现疾速、间断的下载。
privateGrpcChannel _channel =GrpcChannel.ForAddress(…);
privateDownloadClient _client =newDownloadClient(_channel);
[Benchmark]
publicTaskGrpcLargeDownload()=>
_client.DownloadLargeMessageAsync(newEmptyMessage());
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 和 gRPC 的一个个性,而 .NET 6 比以往任何时候都快。客户端负载平衡和 HTTP/3 等以性能为导向的新性能意味着更低的提早、更高的吞吐量和更少的服务器。这是一个节俭资金、缩小能耗和构建更环保的云原生应用程序的机会。
要试用新性能并开始在 .NET 中应用 gRPC,最好的终点是在 ASP.NET Core 教程中创立 gRPC 客户端和服务器。
咱们期待听到无关应用 gRPC 和 .NET 构建的应用程序以及您在 dotnet 和 grpc 存储库中的奉献!
.NET 上的 gRPC 参考文档