本文主要是介绍解决雪崩的方案之一:流量控制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.簇点链路
2.设置流控模式
2.1设置直接流控模式
2.2.设置关联流控模式
2.3设置链路流控模式
2.4总结
3.设置流控效果
3.1warm up 预热模式
3.2排队等待
3.3总结
4.热点参数限流
4.1全局参数限流
4.2热点参数限流
解决雪崩的方案之一:限流,是为了避免服务因突发的流量而发生故障,是预防措施。
1.簇点链路
当请求进入微服务时,首先会访问DispatcherServlet,然后进入Controller、Service、Mapper,这样的⼀个调用链就叫做簇点链路。簇点链路中被监控的每⼀个接口就是⼀个资源。
默认情况下sentinel会监控SpringMVC的每⼀个端点(Endpoint,也就是controller中的方法),因此SpringMVC的每⼀个端点(Endpoint)就是调用链路中的⼀个资源。
流控和熔断都是针对簇点链路中的资源来设置,因此可点击对应资源后面的按钮来设置规则:
- 流控:流量控制
- 降级:降级熔断
- 热点:热点参数限流,是限流的一种
- 授权:请求的权限控制
2.设置流控模式
2.1设置直接流控模式
要求:给/order/prod/{pid}设置流控规则,QPS不能超过5
2.1.1在sentinel控制台添加限流规则
其中的QPS为每秒查询率,即每秒的响应次数,也就是最大吞吐能力,QPS=请求数req/秒sec
2.2利用jmeter测试
- 双击jmeter.bat启动jmeter
即可打开jmeter的界面
- 添加线程组
线程数:代表用户数量
时间:代表用户访问时间
10个线程要在2秒内访问完,那每秒就是访问5个线程
QPS=10/2=5,超过了单机阈值2,所以每秒的5个线程只成功2个,剩下的3个线程会请求失败。
循环次数:代表每个用户的访问次数
- 添加http请求
端口号:写的是sentinel中资源/order/prod/{pid}的端口号8091
路径:写的是给资源添加流控规则就写那个资源,/order/prod/{pid}
- 察看结果树
- 启动测试计划
方式一:单击上面任务栏的启动符号(适用于测试计划中只有一个线程)
方式二:右键单击线程启动(适用于测试计划中有多个线程)
结果:可以看到,成功的请求每次只有2个
2.2.设置关联流控模式
用户购买商品进行下单操作,同时用户要查询订单,业务需求是优先支付和更新订单的业务。因此当下单业务触发阈值时,需要对查询订单业务限流。
2.2.1定义 /order/query和/order/update两个接口在controller层
//关联模式
@GetMapping("/order/query")
public String query(){return "查询订单成功";
}@GetMapping("/order/update")
public String update(){return "下单成功";
}
2.2.2配置流控规则
对哪个资源进行限流操作,就对那个资源添加流控规则
我们对/order/query资源进行限流,因此对/order/query添加流控规则:
当 /order/update资源被访问的QPS超过5时,就会对/order/query资源进行限流。
2.2.3进行Jmeter测试
1000个用户,100秒,因此QPS=1000/100=10,超过了我们设置的阈值5,所以结果会是一组请求10个会成功5个失败5个。
我们的请求目标是/order/update,只要这个接口的请求数量超过5,就会对/order/query进行限流操作,在浏览器对/order/query进行访问,发现被限流
2.3设置链路流控模式
链路模式:只针对指定链路访问到本资源的请求做统计,判断数量是否超过阈值。
有查询订单和创建订单业务,两者都需要查询商品。针对从查询订单进入到查询商品的请求进行统计,并设置限流。
2.3.1在IOrderService中定义一个方法,用来查询商品。
void queryGoods();
默认情况下sentinel不会对@SentinelResource下的方法监控,所以使用@SentinelResource注解来标记要监控的方法。
@SentinelResource("queryGoods")
public void queryGoods(){System.out.println("查询商品");
}
//链路模式
@GetMapping("/order/query")
public String query(){//查询商品orderService.queryGoods();return "查询订单成功";
}@GetMapping("/order/update")
public String update(){//查询商品orderService.queryGoods();return "下单成功";
}
链路模式中,是对不同来源的两个链路做监控。但是sentinel默认会给进入SpringMVC的所有请求设置同一个root资源,会导致链路模式失效。
我们需要关闭这种对SpringMVC的资源聚合,修改order-service服务的application.yml⽂件:
spring:cloud:sentinel:web-context-unify: false # 关闭context整合
2.3.2存在两条统计链路:
- /order/query --> queryGoods
- /order/update--> queryGoods
只统计从/order/query进入到 queryGoods的请求,就对 /queryGoods进行配置:
给queryGoods设置限流规则,从/order/query进入queryGoods的方法限制QPS必须小于2
2.3.3Jmeter测试
对/order/query进行测试:20个用户,4秒内发完,QPS=5,所以5个中会有2个成功,3个失败
如果http请求是/order/update,运行的结果:完全不会受影响
2.4总结
流控模式包括:
- 直接:对当前的资源进行限流
- 关联:关联资源触发阈值,对资源进行限流(高优先级资源触发阈值,对低优先级资源限流)
- 链路:只统计入口资源进入资源的请求,对入口资源进行限流(只统计从指定资源进入当前资源的请求数,是对请求来源的限流)
3.设置流控效果
流控效果是指请求达到流控阈值时应该采取的措施,包括以下三种:
- 快速失败:达到阈值后,新进来的请求就会立刻被拒绝并抛出FlowException异常(默认)
- warm up:预热模式,对超出阈值后进来的请求就是拒绝并抛出异常。但它的阈值是动态变化的,在预热时间后,从一个较小值逐步增加到最大阈值QPS
- 排队等待:让所有的请求排队等待,对超出阈值后进来的请求通过计算等待时间是否在等待时长内,若在,就等待执行;不在则拒绝且抛出异常
3.1warm up 预热模式
阈值一般是一个微服务能承担的最大QPS,但是一个服务刚刚启动时,一切资源尚未初始化(冷启
动),如果直接将QPS跑到最大值,可能导致服务瞬间宕机 。
warm up也叫预热模式,是应对服务冷启动的一种方案。请求阈值初始值是 maxThreshold /
coldFactor,持续指定时长后,逐渐提高到maxThreshold值。而oldFactor的默认值是3.
例如,我设置QPS的maxThreshold为10,预热时间为5秒,那么初始阈值就是 10 / 3 ,也就是3,然后阈值会在5秒后逐渐增长到10.
要求:给/order/prod/{pid}设置限流,最大QPS是10,利用warm up效果,预热时长为10秒
3.1.1配置流控规则
初始阈值为10/3=3
3.1.2Jmeter测试,QPS是10
刚开始启动时,成功的请求只有三个,说明会QPS被限制在3
随着时间的推移,成功的比例越来越高;直到最后全部成功,达到最大阈值
3.2排队等待
当请求超过QPS阈值时,快速失败和warm up 会拒绝新的请求并抛出异常。
而排队等待则是让所有请求进入一个队列中,然后按照阈值允许的时间间隔依次执行。后来的请求必须等待前面执行完成,如果请求预期的等待时间超出最大时长,则会被拒绝。
工作原理
例如:QPS=5,意味着每200ms处理一个队列中的请求(1s/5=200ms),超时时长为2000,意味着预期等待时长超过2000ms的请求会被拒绝并且抛出异常。
预期等待时长:
现在进来了12个去请求,因为每200ms执行一个请求,所以:
一般来说,可以先计算一下超过阈值的第一个请求以及最后一个请求的等待时长
第六个请求的预期等待时长:200*(6-1)=1000ms
第十二个请求的预期等待时长:200*(12-1)=2200ms
发现第十二请求的预期等待时长超出了2000ms,因此第12个请求会被拒绝
再计算第11个请求的等待时长:200*(11-1)=2000ms,刚好在期限内
所以:12个请求中前十一个会成功,最后一个请求会失败
要求:给/order/prod/{pid}设置限流,最大QPS是10,利用排队等待效果,超时时长设置为5s
3.2.1配置流控规则
QPS=10,所以每100ms处理一个队列中的请求
3.2.2Jmeter测试,QPS是15
计算预期等待时长:
第11个:100*(11-1)=1000ms
第15个:100*(15-1)=1400ms
都小于超时时间5000ms,所以15个请求都会通过
3.3总结
流控效果包括:
- 快速失败:QPS超过阈值时,直接拒绝新的请求
- warm up:QPS超过阈值时,拒绝新的请求,但QPS阈值是逐渐提升的,可避免冷启动时高并发导致服务宕机
- 排队等待:请求会进入队列,按照阈值允许的时间间隔依次执行请求;如果请求的预期等待时间大于超时时间,直接拒绝
4.热点参数限流
之前的限流是统计访问某个资源的所有请求,判断是否超过QPS阈值;而热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值
注意:新增热点规则,不要直接点击hot资源后面的按钮,会有BUG出现,需要点击左侧菜单中的热点规则菜单,再点击新增热点限流规则
热点参数限流对默认的SpringMVC资源无效,需要利用@SentinelResource注解标记资源
4.1全局参数限流
一个根据商品的id查商品的接口
对hot这个资源的0号参数,也就是第一个参数pid做统计,每一秒相同参数值的请求数不能超过5
访问/goods/{id}的请求中,id参数值会有变化,热点参数限流会根据参数值分别统计QPS:
当QPS的值超过设置的阈值时,会对该id的请求进行限流;但其他请求的QPS没有超过阈值5的商品不会影响
4.2热点参数限流
全局参数限流是对所有的商品都进行QPS限定为5;
但在实际开发中有些商品是热点商品,我们希望这部分商品的QPS限制与其他商品不一致,此时就需要使用配置热点参数限流的高级选项。
对0号long类型的参数进行限流,每一秒相同参数的QPS不能超过5,但有两个例外:
如果参数值为1,则每秒内允许的QPS为4
如果参数值为2,则每秒内允许的QPS为10
这篇关于解决雪崩的方案之一:流量控制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!