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

「译」 .NET 6 中 gRPC 的新功能的更多相关文章
- 「译」forEach循环中你不知道的3件事
前言 本文925字,阅读大约需要7分钟. 总括: forEach循环中你不知道的3件事. 原文地址:3 things you didn't know about the forEach loop in ...
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
- 「译」JavaScript 的怪癖 1:隐式类型转换
原文:JavaScript quirk 1: implicit conversion of values 译文:「译」JavaScript 的怪癖 1:隐式类型转换 译者:justjavac 零:提要 ...
- jvm系列(十):如何优化Java GC「译」
本文由CrowHawk翻译,是Java GC调优的经典佳作. 本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三 ...
- jvm系列(七):如何优化Java GC「译」
本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. Sangmin Lee发表在Cubrid上的”Become a Java GC Expert”系列文章 ...
- iOS 9,为前端世界都带来了些什么?「译」 - 高棋的博客
2015 年 9 月,Apple 重磅发布了全新的 iPhone 6s/6s Plus.iPad Pro 与全新的操作系统 watchOS 2 与 tvOS 9(是的,这货居然是第 9 版),加上已经 ...
- [译] OpenStack Kilo 版本中 Neutron 的新变化
OpenStack Kilo 版本,OpenStack 这个开源项目的第11个版本,已经于2015年4月正式发布了.现在是个合适的时间来看看这个版本中Neutron到底发生了哪些变化了,以及引入了哪些 ...
- 「译」用 Blazor WebAssembly 实现微前端
原文作者: Wael Kdouh 原文链接:https://medium.com/@waelkdouh/microfrontends-with-blazor-webassembly-b25e4ba3f ...
随机推荐
- Luogu P2024 [NOI2001]食物链 | 并查集
题目链接 思路:并查集,因为一开始我们并不知道每一只动物是哪一个种类的,所以我们干脆建立三倍于n的空间,1~n这三分之一用来存第i只动物是A的情况,n+1~2n这三分之一用来存第(i-n)只动物是B的 ...
- 使用Netty和动态代理实现一个简单的RPC
RPC(remote procedure call)远程过程调用 RPC是为了在分布式应用中,两台主机的Java进程进行通信,当A主机调用B主机的方法时,过程简洁,就像是调用自己进程里的方法一样.RP ...
- PTA 7-2 哈夫曼编码 (30分)
PTA 7-2 哈夫曼编码 (30分) 给定一段文字,如果我们统计出字母出现的频率,是可以根据哈夫曼算法给出一套编码,使得用此编码压缩原文可以得到最短的编码总长.然而哈夫曼编码并不是唯一的.例如对字符 ...
- idea离线安装lombok插件
1.查看自己idea版本,2019.1.2,必须安装相同版本的插件 2.从http://plugins.jetbrains.com/plugin/6317-lombok-plugin中下载对应版本的l ...
- 1. 处理静态资源 2. controller如何接受请求得参数 3. 如何把controller得数据保存到view. 4. 在controller如何完成重定向到指定路径 5. controller返回json数据
1. 1. 处理静态资源2. controller如何接受请求得参数3. 如何把controller得数据保存到view.4. 在controller如何完成重定向到指定路径5. controller ...
- Centos8 Docker部署ElasticSearch集群
ELK部署 部署ElasticSearch集群 1.拉取镜像及批量生成配置文件 # 拉取镜像 [root@VM-24-9-centos ~]# docker pull elasticsearch:7. ...
- python实现圆检测
目录: (一)霍夫圆检测原理 (二)代码实现 (一)霍夫圆检测原理 (二)代码实现 1 #霍夫圆检测 2 import cv2 as cv 3 import numpy as np 4 5 def d ...
- [atARC123F]Insert Addition
前置知识 下面,先来介绍一下Stern-Brocot Tree的结构: 其是一棵满二叉树,每一个节点都是一个最简分数,其中根为$\frac{1}{1}$ 假设前$i$层的中序遍历分数依次为$\frac ...
- [hdu6580]Milk
考虑定义以下dp数组:1.g1[i][j]表示第i行从中间出发向左取j瓶牛奶最少要多久2.g2[i][j]表示第i行从中间出发向右取j瓶牛奶最少要多久3.g3[i][j]表示在g1[i][j]的基础上 ...
- [cf1349E]Slime and Hats
首先,当发现全场不存在黑色帽子时,显然所有人都知道其是白色帽子,即必然离开 当第一轮时,若第$n$个人发现前面$n-1$个人全是白色时,其自己必然是黑色,必然离开 而第二轮时,若第$n-1$个人发现$ ...