解决雪崩的方案之一:流量控制

2024-08-25 09:20

本文主要是介绍解决雪崩的方案之一:流量控制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

                        ​​​​​​​   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

这篇关于解决雪崩的方案之一:流量控制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1105159

相关文章

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

mysql出现ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的解决方法

《mysql出现ERROR2003(HY000):Can‘tconnecttoMySQLserveron‘localhost‘(10061)的解决方法》本文主要介绍了mysql出现... 目录前言:第一步:第二步:第三步:总结:前言:当你想通过命令窗口想打开mysql时候发现提http://www.cpp

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu

springboot报错Invalid bound statement (not found)的解决

《springboot报错Invalidboundstatement(notfound)的解决》本文主要介绍了springboot报错Invalidboundstatement(not... 目录一. 问题描述二.解决问题三. 添加配置项 四.其他的解决方案4.1 Mapper 接口与 XML 文件不匹配

Python中ModuleNotFoundError: No module named ‘timm’的错误解决

《Python中ModuleNotFoundError:Nomodulenamed‘timm’的错误解决》本文主要介绍了Python中ModuleNotFoundError:Nomodulen... 目录一、引言二、错误原因分析三、解决办法1.安装timm模块2. 检查python环境3. 解决安装路径问题

IDEA中Git版本回退的两种实现方案

《IDEA中Git版本回退的两种实现方案》作为开发者,代码版本回退是日常高频操作,IntelliJIDEA集成了强大的Git工具链,但面对reset和revert两种核心回退方案,许多开发者仍存在选择... 目录一、版本回退前置知识二、Reset方案:整体改写历史1、IDEA图形化操作(推荐)1.1、查看提

如何解决mysql出现Incorrect string value for column ‘表项‘ at row 1错误问题

《如何解决mysql出现Incorrectstringvalueforcolumn‘表项‘atrow1错误问题》:本文主要介绍如何解决mysql出现Incorrectstringv... 目录mysql出现Incorrect string value for column ‘表项‘ at row 1错误报错

如何解决Spring MVC中响应乱码问题

《如何解决SpringMVC中响应乱码问题》:本文主要介绍如何解决SpringMVC中响应乱码问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring MVC最新响应中乱码解决方式以前的解决办法这是比较通用的一种方法总结Spring MVC最新响应中乱码解

Java报NoClassDefFoundError异常的原因及解决

《Java报NoClassDefFoundError异常的原因及解决》在Java开发过程中,java.lang.NoClassDefFoundError是一个令人头疼的运行时错误,本文将深入探讨这一问... 目录一、问题分析二、报错原因三、解决思路四、常见场景及原因五、深入解决思路六、预http://www