.Net Core gRPC 实战(二)
概述
gRPC 客户端必须使用与服务相同的连接级别安全性。 如调用服务时通道和服务的连接级别安全性不一致,gRPC 客户端就会抛出错误。
gRPC 配置使用HTTP
gRPC 客户端传输层安全性 (TLS) 是在创建 gRPC 通道时服务器地址以https开头配置的。若要配置为http协议做如下修改
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
GrpcChannel.ForAddress("http://localhost:5000")
关于通道和客户端的说明
- 创建通道成本高昂。 重用 gRPC 调用的通道可提高性能。
- gRPC 客户端是使用通道创建的。 gRPC 客户端是轻型对象,无需缓存或重用。
配置截止时间
建议配置 gRPC 调用的截止时间,因为它限制调用时间的上限,阻止异常运行的服务持续运行并耗尽服务器资源。 截止时间对于构建可靠应用非常有效。
进行调用时,使用 CallOptions.Deadline 配置截止时间。
如果超过了截止时间,客户端和服务将有不同的行为:
- 客户端将立即中止基础的 HTTP 请求并引发
DeadlineExceeded错误。 客户端可以选择捕获错误并向用户显示超时消息。 - 服务器将中止正在执行的 HTTP 请求,并引发 ServerCallContext.CancellationToken。 尽管中止了 HTTP 请求,gRPC 调用仍将继续运行直到方法完成。 将取消令牌传递给异步方法,使其随调用一同被取消。 例如,向异步数据库查询和 HTTP 请求传递取消令牌。 传递取消令牌让取消的调用可以在服务器上快速完成,并为其他调用释放资源。
客户端代码示例:
try
{
var response = await client.SayHelloAsync(
new HelloRequest { Name = "World" },
deadline: DateTime.UtcNow.AddSeconds(5)); // Greeting: Hello World
Console.WriteLine("Greeting: " + response.Message);
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.DeadlineExceeded)
{
Console.WriteLine("Greeting timeout.");
}
服务器代码示例:
var response = await client.GetUserAsync(
new UserRequest { Id = request.Id },
deadline: context.Deadline);
注册 gRPC 客户端
在 Startup类的ConfigureServices方法中,使用 AddGrpcClient 扩展方法指定 gRPC客户端类和服务地址。
services.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
});
ASP.NET Core MVC 控制器和 gRPC 服务等通过构造函数等方式自动注入。
配置 HttpHandler
.ConfigurePrimaryHttpMessageHandler(() => new GrpcWebHandler(GrpcWebMode.GrpcWebText, new HttpClientHandler()));
配置通道和拦截器
通道
通道(Channel)是.Net Core 3.X引入的类型,Channel是线程安全的,Channel的预期用例是多线程场景,可以实现多线程之间通信。类似Golang的chan类型。
通道相关文章:https://webmote.blog.csdn.net/article/details/115361367
gRPC配置通道示例:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigureChannel(o =>
{
var credentials = CallCredentials.FromInterceptor((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
}); o.Credentials = ChannelCredentials.Create(new SslCredentials(), credentials);
});
拦截器
具有面向切面的思想,可以在调用服务的时候进行一些统一处理, 很适合在这里处理验证、日志等流程。
Interceptor类是gRPC服务拦截器的基类,是一个抽象类

各个方法作用如下:
|
方法名称 |
作用 |
|---|---|
|
BlockingUnaryCall |
拦截阻塞调用 |
|
AsyncUnaryCall |
拦截异步调用 |
|
AsyncServerStreamingCall |
拦截异步服务端流调用 |
|
AsyncClientStreamingCall |
拦截异步客户端流调用 |
|
AsyncDuplexStreamingCall |
拦截异步双向流调用 |
|
UnaryServerHandler |
用于拦截和传入普通调用服务器端处理程序 |
|
ClientStreamingServerHandler |
用于拦截客户端流调用的服务器端处理程序 |
|
ServerStreamingServerHandler |
用于拦截服务端流调用的服务器端处理程序 |
|
DuplexStreamingServerHandler |
用于拦截双向流调用的服务器端处理程序 |
在实际使用中,可以根据自己的需要来使用对应的拦截方法。
本文示例为创建一个客户端拦截器ClientLoggerInterceptor,该类继承Interceptor。按需实现方法,这里我客户端调用的是SayHelloAsync方法则实现对应的AsyncUnaryCall方法。

注册拦截器:

运行效果图:

服务器端拦截器同理,继承Interceptor类实现对应方法。
服务器端注入方式:
services.AddGrpc(options =>
{
options.Interceptors.Add<ServerLoggerInterceptor>();
});
调用取消
可以使用 EnableCallContextPropagation() 对 gRPC 服务中工厂所创建的 gRPC 客户端进行配置,以自动将截止时间和取消令牌传播到子调用。
手动传播截止时间可能会很繁琐。 截止时间需要传递给每个调用,很容易不小心错过。 gRPC 客户端工厂提供自动解决方案。 指定 EnableCallContextPropagation:
- 自动将截止时间和取消令牌传播到子调用。
- 这是确保复杂的嵌套 gRPC 场景始终传播截止时间和取消的一种极佳方式。
services
.AddGrpcClient<User.UserServiceClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.EnableCallContextPropagation();
如果客户端在 gRPC 调用的上下文之外使用,EnableCallContextPropagation 将引发错误。 此错误旨在提醒你没有要传播的调用上下文。 如果要在调用上下文之外使用客户端,请使用 SuppressContextNotFoundErrors 在配置客户端时禁止显示该错误:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.EnableCallContextPropagation(o => o.SuppressContextNotFoundErrors = true);
配置 gRPC 重试策略
重试策略在创建 gRPC 通道时配置
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("http://localhost:5000",
new GrpcChannelOptions
{
LoggerFactory = loggerFactory,
ServiceConfig = new ServiceConfig
{
MethodConfigs = { defaultMethodConfig }
}
});
重试策略可以按方法配置,而方法可以使用
Names属性进行匹配。 此方法配置有MethodName.Default,因此它将应用于此通道调用的所有 gRPC 方法。
gRPC 重试选项
下表描述了用于配置 gRPC 重试策略的选项:
| 选项 | 描述 |
|---|---|
MaxAttempts |
最大调用尝试次数,包括原始尝试。 此值受 GrpcChannelOptions.MaxRetryAttempts(默认值为 5)的限制。 必须为该选项提供值,且值必须大于 1。 |
InitialBackoff |
重试尝试之间的初始退避延迟。 介于 0 与当前退避之间的随机延迟确定何时进行下一次重试尝试。 每次尝试后,当前退避将乘以 BackoffMultiplier。 必须为该选项提供值,且值必须大于 0。 |
MaxBackoff |
最大退避会限制指数退避增长的上限。 必须为该选项提供值,且值必须大于 0。 |
BackoffMultiplier |
每次重试尝试后,退避将乘以该值,并将在乘数大于 1 的情况下以指数方式增加。 必须为该选项提供值,且值必须大于 0。 |
RetryableStatusCodes |
状态代码的集合。 具有匹配状态的失败 gRPC 调用将自动重试。 有关状态代码的更多信息,请参阅状态代码及其在 gRPC 中的用法。 至少需要提供一个可重试的状态代码。 |
配置 gRPC hedging 策略
Hedging 是一种备选重试策略。 Hedged gRPC 调用可以在服务器上执行多次,并获取第一个成功的结果。
重要的是,务必仅针对可安全执行多次且不会造成负面影响的方法启用 hedging。且hedging 策略不能与重试策略结合使用。
Hedging 具有以下优缺点:
- Hedging 的优点是,它可能更快地返回成功的结果。 它允许同时进行多个 gRPC 调用,并在出现第一个成功的结果时完成。
- Hedging 的一个缺点是它可能会造成浪费。 进行了多个调用并且这些调用全部成功。 仅使用第一个结果放弃其余结果。
Hedging 策略的配置类似于重试策略:
var defaultMethodConfig = new MethodConfig
{
Names = { MethodName.Default },
HedgingPolicy = new HedgingPolicy
{
MaxAttempts = 5,
NonFatalStatusCodes = { StatusCode.Unavailable }
}
}; var channel = GrpcChannel.ForAddress("http://localhost:5000", new GrpcChannelOptions
{
LoggerFactory = loggerFactory,
ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
});
gRPC hedging 选项
下表描述了用于配置 gRPC hedging 策略的选项:
| 选项 | 描述 |
|---|---|
MaxAttempts |
Hedging 策略将发送的调用数量上限。 MaxAttempts 表示所有尝试的总数,包括原始尝试。 此值受 GrpcChannelOptions.MaxRetryAttempts(默认值为 5)的限制。 必须为该选项提供值,且值必须大于 2。 |
HedgingDelay |
第一次调用立即发送,但后续 hedging 调用将按该值延迟发送。 如果延迟设置为零或 null,那么所有所有 hedged 调用都将立即发送。 默认值为 0。 |
NonFatalStatusCodes |
指示其他 hedge 调用仍可能会成功的状态代码集合。 如果服务器返回非致命状态代码,hedged 调用将继续。 否则,将取消未完成的请求,并将错误返回到应用。 有关状态代码的更多信息,请参阅状态代码及其在 gRPC 中的用法。 |
Github
本文示例代码:https://github.com/MayueCif/GrpcDemo
.Net Core gRPC 实战(二)的更多相关文章
- .Net Core gRPC 实战(一)
gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架. gRPC 的主要优点是: 现代高性能轻量级 RPC 框架. 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现. 可用 ...
- 【无私分享:ASP.NET CORE 项目实战(第十二章)】添加对SqlServer、MySql、Oracle的支持
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 增加对多数据库的支持,并不是意味着同时对多种数据库操作,当然,后面,我们会尝试同时对多种数据库操作,这可能需要多个上下文,暂且 ...
- 【.NET Core项目实战-统一认证平台】第十二章 授权篇-深入理解JWT生成及验证流程
[.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章介绍了基于Ids4密码授权模式,从使用场景.原理分析.自定义帐户体系集成完整的介绍了密码授权模式的内容,并最后给出了三个思考问题,本 ...
- .net core grpc consul 实现服务注册 服务发现 负载均衡(二)
在上一篇 .net core grpc 实现通信(一) 中,我们实现的grpc通信在.net core中的可行性,但要在微服务中真正使用,还缺少 服务注册,服务发现及负载均衡等,本篇我们将在 .net ...
- java版gRPC实战之二:服务发布和调用
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 【无私分享:ASP.NET CORE 项目实战(第八章)】读取配置文件(二) 读取自定义配置文件
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 我们在 读取配置文件(一) appsettings.json 中介绍了,如何读取appsettings.json. 但随之产生 ...
- ASP.NET Core gRPC 入门全家桶
一. 说明 本全家桶现在只包含了入门级别的资料,实战资料更新中. 二.官方文档 gRPC in Asp.Net Core :官方文档 gRPC 官网:点我跳转 三.入门全家桶 正片: ASP.NET ...
- 【无私分享:ASP.NET CORE 项目实战】目录索引
简介 首先,我们的 [无私分享:从入门到精通ASP.NET MVC] 系列已经接近尾声,希望大家在这个过程中学到了一些思路和方法,而不仅仅是源码. 因为是第一次写博客,我感觉还是比较混乱的,其中 ...
- 【无私分享:ASP.NET CORE 项目实战(第十四章)】图形验证码的实现
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 很长时间没有来更新博客了,一是,最近有些忙,二是,Core也是一直在摸索中,其实已经完成了一个框架了,并且正在准备在生产环境中 ...
随机推荐
- 1.1.09- 序列赋值 is , is not运算符
两个变量的交换算法 代码如下: a = 10000 b = 20000 temp = a a = b b = temp print(a) print(b) 序列赋值: a,b = b,aprint(a ...
- 记一次linux下安装ftp的愉快体验
三三两两,试了几次就出来了,挺开心的 linux安装vsftpd,请自行百度 贴出部分配置点 阿里云服务器,开发相关端口以及部分区域端口访问 /etc/pad.d/vsftpd添加部分注释 #%PAM ...
- 关于width的继承和获取
absolute元素(如果没有设置width值),其宽度自适应于内部元素, <!DOCTYPE html> <html lang="en"> <hea ...
- hdu3756 三分求最小圆锥
题意: 让你找到一个最小的圆柱去覆盖所有的竖直的线段.. 思路: 三分,直接去三分他的半径,因为想下,如果某个半径是最优值,那么 从R(MAX->now->MIN) ...
- LA3902网络
题意: 给你一棵树,所有叶子节点都是客户端,其他的都是服务器,然后问你最少在多少个服务器上安装VOD能使所有的客户端都能流畅的看视频,流畅看视频的条件是每个客户端距离他最近的安装VOD的服务 ...
- Python中Scapy网络嗅探模块的使用
目录 Scapy scapy的安装和使用 发包 发包和收包 抓包 将抓取到的数据包保存 查看抓取到的数据包 格式化输出 过滤抓包 Scapy scapy是python中一个可用于网络嗅探的非常强大的第 ...
- 缓冲区溢出之栈溢出利用(手动编写无 payload 的 Exploit)
0x01 介绍 Exploit 的英文意思就是利用,它在黑客眼里就是漏洞利用.有漏洞不一定就有Exploit(利用),有Exploit就肯定有漏洞.编写缓冲区溢出的Exploit分为3个方面:漏洞溢出 ...
- windows安装TeX Live 2019及TeXstudio
废话不多说,先放资源链接: 链接:https://pan.baidu.com/s/1XYXNJvmVfBoe9rSdTnZDBw 提取码:xjor视频安装教程我会在评论区放上B站链接(如果我有心情剪的 ...
- Win10安装Ubuntu子系统(WSL)
一:设置子系统环境 关闭所有运行的程序,打开 控制面板→卸载程序→启用或关闭windows功能→勾选上适用于Linux的windows子系统 ,然后确定,完成会提示重启电脑,确定重启,等重启电脑后在操 ...
- PHP 上传文件至阿里云OSS对象存储
简述 1.阿里云开通对象存储服务 OSS 并创建Bucket 2.下载PHP SDK至框架扩展目录,点我下载 3.码上code 阿里云操作 开通对象存储服务 OSS 创建 Bucket 配置Acces ...