gRPC 是一个现代的、跨平台的、高性能的 RPC 框架。gRPC 是构建在 ASP.NET Core 之上,也是我们推荐的使用 .NET 构建 RPC 服务的方法。
.NET 6 进一步提高了 gRPC 已经非常出色的性能,并添加了一系列新功能,使 gRPC 在现代云原生应用程序中比以往任何时候都更好。在这篇文章中,我将描述这些新功能以及我们如何通过第一个支持端到端 HTTP/3 的 gRPC 实现引领行业。
gPRC 客户端负载均衡
客户端负载平衡是一项允许 gRPC 客户端在可用服务器之间优化分配负载的功能。客户端负载平衡可以消除对负载平衡代理的需要。这有几个好处:
- 改进的性能。无代理意味着消除额外的网络跃点并减少延迟,因为 RPC 直接发送到 gRPC 服务器。
- 有效利用服务器资源。负载平衡代理必须解析然后重新发送通过它发送的每个 HTTP 请求。删除代理可以节省 CPU 和内存资源。
- 更简单的应用程序架构。必须正确设置和配置代理服务器。没有代理服务器意味着更少的活动部件!
- 解析器,解析通道的地址。解析器支持从外部源获取地址。这也称为服务发现。
- 负载均衡器,它创建连接并选择 gRPC 调用将使用的地址。
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 调用可能会被瞬时故障中断。瞬态故障包括:
- 网络连接暂时中断。
- 服务暂时不可用。
- 由于服务器负载超时。
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
protocolbuffers/protobuf#8147添加了矢量化字符串序列化。SIMD 指令允许并行处理多个字符,从而在序列化某些字符串值时显着提高性能。
privatestring _value =https://www.it610.com/article/newstring(' ',10080);
privatebyte[] _outputBuffer =newbyte[10080];
[Benchmark]
publicvoidWriteString()
{
var span =newSpan(_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 6 中 gRPC 的最新功能】.NET 上的 gRPC参考文档
推荐阅读
- 记一次 .NET 某药品仓储管理系统 卡死分析
- IIS发布.net连接不上数据库解决办法
- 利用Visual Studio 2017的扩展开发(VSIX、ItemTemplate) 快速实现项目的半自动化搭建
- C#进度条实现
- .net|利用MSXML2.XMLHTTP的无刷新技术
- 配置VS2008中文版调试.netframework源代码
- .net|解决Win8.1下VS2005编辑报错的问题
- Java与C#间json时间格式互转完美解决方案
- 在VS.NET内使用“从源代码管理打开”时出现无法读取项目文件的错误