Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级
相关文章
Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现
Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网关Ocelot+Consul
Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级
环境Ocelot包版本17.0.0
一、简介
Polly 是一个 .NET 弹性和瞬态故障处理库,允许开发人员以线程安全的方式来实现重试、断路、超时、隔离和回退策略。
瞬态故障就是可能会出现的,比喻网络不稳定或无法访问,或服务宕机。
二、Ocelot各种策略使用和解释
下面各种策略都是基于前一篇Ocelot+Consul的配置基础上修改。
2.1Ocelot缓存
缓存能有效提升程序性能
在ocelot.json中增加缓存配置
{
"Routes": [
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/api/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询
},
//上游地址
"UpstreamPathTemplate": "/T1/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"UseServiceDisConvery": true, //使用服务发现
"ServiceName": "api", //Consul服务名称
//缓存设置
"FileCacheOptions": {
"TtlSeconds": 10, //缓存10s(同一个地址请求就返回缓存结果)
"Region": ""//缓存region
}
}
],
"GlobalConfiguration": {
//Ocelot应用地址
"BaseUrl": "http://172.16.2.9:5200",
"ServiceDiscoveryProvider": {
//Consul地址
"Host": "172.16.2.84",
//Consul端口
"Port": 8500,
"Type": "Consul"//由Consul提供服务发现,每次请求Consul
}
}
}
缓存是针对下游地址缓存的,同一个地址请求返回相同数据,所以针对一些不变的数据才能做缓存,根据用户登录信息不同返回不同数据的就不能做了。
测试:访问 http://172.16.2.9:5200/T1/Test/GetName
刷新后还是5201端口数据,说明是从缓存取的
10s后刷新端口变成5202
2.2Ocelot限流
为什么要限流呢,防止请求过多把程序搞宕机了,也可以有效防止爬虫和ddos攻击,预估出服务的处理能力,然后设置限流,可以限制单位时间内的访问量(失败一部分请求比整个服务挂掉强)。
ocelot.json文件增加限流配置
{
"Routes": [
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/api/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询
},
//上游地址
"UpstreamPathTemplate": "/T1/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"UseServiceDisConvery": true, //使用服务发现
"ServiceName": "api", //Consul服务名称
//限流配置
"RateLimitOptions": {
"ClientWhitelist": [ "admin" ], // 白名单
"EnableRateLimiting": true, // 是否启用限流
"Period": "10s", // 统计时间段:1s, 5m, 1h, 1d
"PeriodTimespan": 10, // 多少秒之后客户端可以重试
"Limit": 5 // 在统计时间段内允许的最大请求数量
}
}
],
"GlobalConfiguration": {
//Ocelot应用地址
"BaseUrl": "http://172.16.2.9:5200",
"ServiceDiscoveryProvider": {
//Consul地址
"Host": "172.16.2.84",
//Consul端口
"Port": 8500,
"Type": "Consul" //由Consul提供服务发现,每次请求Consul
},
//限流
"RateLimitOptions": {
"QuotaExceededMessage": "errr:request fast!", //限流后响应内容
"HttpStatusCode": 666, //http状态码可以自定义
"ClientIdHeader": "client_id" // 用来识别客户端的请求头,默认是 ClientId
}
}
}
这里用Postman来演示比较直观。
可以看到,在10s内请求了5次之后的请求就失败了,返回的状态码是自定义的666,然后等10s过后又恢复访问,上面设置的白名单在Headers加上就可以
不受限流影响,可以无限访问。
2.3Ocelot+Polly的熔断
安装NuGet包 Ocelot.Provider.Polly。
Startup.cs增加 .AddPolly()
public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot()
.AddConsul()
.AddPolly();
}
Ocelot.Provider.Polly的熔断机制是一个超时和熔断的组合,(Polly有超时策略,熔断策略,这里是2个策略的结合使用,下面Polly策略会说到),所以如果是单单是服务报500异常是触发不了的。
接口超过多长时间进入半熔断状态,返回服务不可用, 连续超过多少次进入熔断状态就直接停掉该请求返回,多长时间再恢复。
修改ocelot.json配置
//*****************************单地址********************************
{
"Routes": [
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/api/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询
},
//上游地址
"UpstreamPathTemplate": "/T1/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"UseServiceDisConvery": true, //使用服务发现
"ServiceName": "api", //Consul服务名称
//熔断设置
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, //允许多少个异常请求
"DurationOfBreak": 5000, // 熔断的时间5s,单位为ms
"TimeoutValue": 5000 //单位ms,如果下游请求的处理时间超过多少则自如将请求设置为超时 默认90秒
}
}
],
"GlobalConfiguration": {
//Ocelot应用对外地址
"BaseUrl": "http://172.16.2.9:5200",
"ServiceDiscoveryProvider": {
//Consul地址
"Host": "172.16.2.84",
//Consul端口
"Port": 8500,
"Type": "Consul" //由Consul提供服务发现,每次请求Consul
}
}
}
在之前启动的3个服务增加一个抛异常的接口和一个睡眠接口。
[Route("api/[controller]/[action]")]
public class TestController : Controller
{
private IConfiguration _configuration;
public TestController(IConfiguration configuration)
{
_configuration = configuration;
}
public IActionResult GetName()
{
string port = _configuration["port"];
return Json($"端口:{port},姓名:张三");
}public IActionResult GetSleep()
{
string port = _configuration["port"]; //线程睡眠6s
Thread.Sleep(6000);
return Json($"端口:{port},睡眠6s后返回");
}
}
访问GetSleep()接口,前三次等待6s返回503,后面访问什么接口都是快速返回503,服务熔断。
三、Polly各种策略使用和解释
上面网关处做了Ocelot+Polly的熔断策略,然后服务链上也是需要做一些策略,这里介绍的是在服务里用Polly做各种常用的策略。
3.1Polly降级
降级就是当我们指定的代码处理失败时就执行我们备用的代码。
现在在之前的三个服务中加入Polly降级策略
安装NuGet包 --Polly
新建一个OrderController.cs
[Route("api/[controller]/[action]")]
public class OrderController : Controller
{
private readonly OrderService _orderService;
public OrderController(OrderService orderService)
{
_orderService = orderService;
}
public IActionResult CreateOrder()
{
string result = _orderService.CreateOrder();
return Content(result);
}
}
新建一个OrderService.cs
public class OrderService
{
private Policy<string> _policy;
public OrderService()
{
//降级
_policy = Policy<string>
.Handle<Exception>() //异常故障
.Fallback(() =>
{
//降级回调 todo降级后逻辑
return "降级后的值";
}); }
public string CreateOrder()
{
//用polly执行
return _policy.Execute(() =>
{
//业务逻辑 todo
Console.WriteLine($"{DateTime.Now},开始处理业务"); throw new Exception("233出错啦");
Console.WriteLine("处理完成");
return "成功啦";
});
}
}
把OrderService注入IOC容器,注意,使用Polly时,实例一定要以单例模式注入,因为如果是每次都执行构造函数给_policy赋一次值,那_policy每次都是全新的,下面的熔断策畋会不生效。
Startup.cs中的ConfigureServices()加上
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddControllers().AddJsonOptions(cfg =>
{
services.AddSingleton<OrderService>();
}
测试,访问http://ip:端口/api/Order/CreateOrder
可以看到返回的是降级后处理的值。
3.2Polly熔断
熔断就是当一处代码报错超过多少次,就让它熔断多长时间再恢复,熔断时Polly会截断请求,不会再进入到具体业务,这能有效减少没必要的业务性能损耗。
把OrderService构建函数处改成
public OrderService()
{
//熔断
_policy = Policy<string>.Handle<Exception>()
.CircuitBreaker(5, TimeSpan.FromSeconds(10));//连续出错5次后熔断10秒,不会在进到业务代码 }
测试结果:
5次前的返回:
熔断后返回:
3.3Polly重试
把OrderService的构造函数处修改为:
public OrderService()
{
//重试
//RetryForever()是一直重试直到成功
//Retry()是重试最多一次;
//Retry(n) 是重试最多n次;
//WaitAndRetry()可以实现“如果出错等待100ms再试还不行再等150ms秒。
_policy = Policy<string>.Handle<Exception>()
.WaitAndRetry(new TimeSpan[] { TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15) }); }
这里是业务处理失败时,重试3次,分别隔5s,10s,15s。
测试结果:
可以看到,第一次执行因为有异常,然后分别隔5s,10s,15s重试,最后才抛出了异常。
3.4Polly超时
所谓超时,就是我们指定一段代码的最大运行时间,如果超过这段时间还没有完成,就直接抛出异常。
这里判断超时有两种策略:一个是悲观策略(Pessimistic),一个是乐观策略(Optimistic)。一般我们用悲观策略。需要注意的是,虽然超时抛除了异常,但这段代码的运行并没有停止!
把OrderService构建函数处改成
public OrderService()
{
//超时,业务处理超过3秒就直接返回异常
_policy = Policy.Timeout<string>(3, Polly.Timeout.TimeoutStrategy.Pessimistic);
}
把OrderService.cs的CreateOrder()方法让线程睡眠10s
public string CreateOrder()
{
//用polly执行
return _policy.Execute(() =>
{
//业务逻辑 todo
Console.WriteLine($"{DateTime.Now},开始处理业务");
Thread.Sleep(10000); //睡眠10s
Console.WriteLine("处理完成");
return "成功啦";
});
}
执行查看结果:
可以看到,在3s的时候报了polly的超时异常。
3.5Polly组合策略
上面说的都是单个策略的,其实这些策略是可以组合一起使用的,下面来演示一下。
把OrderService的构造函数修改为:
public OrderService()
{
//重试
Policy<string> retry = Policy<string>.Handle<Exception>()
.WaitAndRetry(new TimeSpan[] { TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15) }); //降级
Policy<string> fallback = Policy<string>
.Handle<Exception>() //异常故障
.Fallback(() =>
{
//降级回调
return "降级后的值";
});
//Wrap:包裹。policyRetry在里面,policyFallback裹在外面。
//如果里面出现了故障,则把故障抛出来给外面
//_policy=Policy.Wrap(policy1, policy2, policy3, policy4, policy5);把更多一起封装。
_policy = Policy.Wrap(fallback, retry); // fallback.Wrap<string>(retry);
}
把CreateOrder()修改为
public string CreateOrder()
{
//用polly执行
return _policy.Execute(() =>
{
//业务逻辑 todo
Console.WriteLine($"{DateTime.Now},开始处理业务");
throw new Exception("233出错啦");
Console.WriteLine("处理完成");
return "成功啦";
});
}
测试结果:
重试3次后,返回降级的结果。
上面的Ocelot+Polly的熔断如果去查看Ocelot.Provider.Polly的源码就会发现是超时和熔断的组合实现。
需要注意的是,组合时Policy.Wrap(fallback, retry);里面的顺序也要注意,测试结果是先执行后面的,再执行前面的,即前面的把后面的包在内层,内层执行完再抛出给外层处理。
上面介绍了最常用的策略,Polly也有异步的方法,把上面定义的private Policy<string> _policy; 改成 private AsyncPolicy<string> _policy; 即可。
Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级的更多相关文章
- Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网关Ocelot+Consul
相关文章 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网 ...
- Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现
环境 .NET5,Consul_v1.10.2 一.简介 在微服务中利用Consul可以实现服务的注册,服务发现,治理,健康检查等. Web调站点需要调用多个服务,如果没有Consul,可能就是Web ...
- .Net微服务实践(四)[网关]:Ocelot限流熔断、缓存以及负载均衡
目录 限流 熔断 缓存 Header转化 HTTP方法转换 负载均衡 注入/重写中间件 后台管理 最后 在上篇.Net微服务实践(三)[网关]:Ocelot配置路由和请求聚合中我们介绍了Ocelot的 ...
- .Net Core的API网关Ocelot的使用(二)[负载,限流,熔断,Header转换]
网关的负载均衡 当下游拥有多个节点的时候,我们可以用DownstreamHostAndPorts来配置 { "UpstreamPathTemplate": "/Api_A ...
- .Net Core使用Ocelot网关(一) -负载,限流,熔断,Header转换
1.什么是API网关 API网关是微服务架构中的唯一入口,它提供一个单独且统一的API入口用于访问内部一个或多个API.它可以具有身份验证,监控,负载均衡,缓存,请求分片与管理,静态响应处理等.API ...
- Redis解读(4):Redis中HyperLongLog、布隆过滤器、限流、Geo、及Scan等进阶应用
Redis中的HyperLogLog 一般我们评估一个网站的访问量,有几个主要的参数: pv,Page View,网页的浏览量 uv,User View,访问的用户 一般来说,pv 或者 uv 的统计 ...
- .NetCore中使用ExceptionLess记录Polly中的操作异常日志
结合上一篇文章我写了一个demo测试下 重试2次 _polly.PollyRetry<Exception>(()=>_demoQuery.GetTestAOPAsync(), ); ...
- Ocelot简易教程(一)之Ocelot是什么
作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9557375.html Ocelot简易教程目录 Ocelot简易教程(一)之Ocelot是什么 Ocel ...
- 熔断 降级(polly)
熔断 降级(polly) https://www.cnblogs.com/szlblog/p/9300845.html1.熔断降级的概念: 熔断:我这里有一根长度一米的钢铁,钢铁的熔点1000度(假设 ...
随机推荐
- javascript html 鼠标放大镜效果
1.鼠标放大镜效果 鼠标放大镜效果,将鼠标移入到左图片,则可以在其右边看到放大的图片,且鼠标移动滑块的大小即为右图显示图片.实际效果如下图所示: <!DOCTYPE html> < ...
- ajax传字符串时出现乱码问题的解决
字符乱码的解决: 第一种在@RequestMapping中添加 @RequestMapping(value="queryAllToTree",method=RequestMetho ...
- layui关闭弹出框
layer.close(index) - 关闭特定层 //当你想关闭当前页的某个层时 var index = layer.open(); var index = layer.alert(); var ...
- 【java虚拟机】内存溢出与内存泄漏
作者:平凡希 原文地址:https://www.cnblogs.com/xiaoxi/p/7354857.html 一.基本概念 内存溢出:简单地说内存溢出就是指程序运行过程中申请的内存大于系统能够提 ...
- 【springcloud】常见面试题总结
1.springcloud与dubbo的区别? https://jingyan.baidu.com/article/b0b63dbf3784294a483070fa.html 1.1 springcl ...
- springcloud starter(一)
Spring Cloud - Getting Started Example, 转载自:https://www.logicbig.com/tutorials/spring-framework/spri ...
- WPF路由事件
这节讲一下WPF中的路由事件(Routed Event). [什么是事件] 在了解路由事件前,我们应先来了解一下什么是事件(Event). 在Windows系统中,像鼠标单击,双击,移动这样 ...
- springboot中redis取缓存类型转换异常
异常如下: [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested ...
- MySQL-存储引擎-1
一.MySQL存储引擎 mysql> create table country( -> country_id smallint unsigned not null auto_increme ...
- 【XSS】XSS修炼之独孤九剑
题目地址 xcao.vip/test 题目作者给出的解题思路 http://xcao.vip/test/xss/XSS修炼之独孤九剑.pdf 独孤九剑-第一式 题目 过滤了等号 =.小括号 (),要求 ...