文章目录
- 前言
- 2 流量控制
- 2.4 流控效果
- 2.4.1 warm up
- 2.4.2 排队等待
- 2.5 热点参数限流
- 2.5.1 全局参数限流
- 2.5.2 热点参数限流
前言
微服务保护学习笔记(一)雪崩问题及解决方案、Sentinel介绍与安装
微服务保护学习笔记(二)簇点链路、流控操作、流控模式(关联、链路)
2 流量控制
2.4 流控效果
在流控的高级选项中,还有一个“流控效果“选项:
流控效果是指请求达到流控阈值时应该采取的措施,包括三种:
- 快速失败:达到阈值后,新的请求会被立即拒绝并抛出异常。是默认的处理方式。
- warm up:预热模式,对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值。
- 排队等待:让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长。
2.4.1 warm up
阈值一般是一个微服务能承担的最大QPS,但是一个服务刚刚启动时,一切资源尚未初始化(冷启动),如果直接将QPS跑到最大值,就可能导致服务瞬间宕机。
warm up也叫预热模式,是应对服务冷启动的一种方案。请求阈值初始值是 maxThreshold / coldFactor,coldFactor的默认值是3,持续指定时长后,逐渐提高到 maxThreshold 值。
例如,设置QPS的 maxThreshold 为10,预热时间为5秒,那么初始阈值就是 10 / 3,也就是3,然后在5秒后逐渐增长到10。
下面对预热模式进行测试:
- 1)给
/user/query
资源设置限流,最大QPS为10,流控效果选择预热模式,预热时常5秒
- 2)使用jmeter工具进行测试
刚启动时,大部分请求失败,成功的只有3个,说明QPS被限定为3:
随着时间的推移,成功比例越来越高:
- 3)Sentinel控制台查看实时监控,也可以看到这种变化趋势
2.4.2 排队等待
当请求超过QPS阈值时,快速失败和warm up会拒绝新的请求并抛出异常。
而排队等待则是让所有请求进入一个队列中,然后按照阈值允许的时间间隔依次执行。后来的请求必须等待前面执行完成,如果请求预期的等待时间超出最大时长,则会被拒绝。
例如:QPS = 5,意味着每200ms处理一个队列中的请求;timeout = 2000,意味着预期等待时长超过2000ms的请求(第12个请求预期等待时长=200ms*(12-1)=2200ms)会被拒绝并抛出异常。
由于所有进入服务的请求都要排队,以固定的200ms的间隔执行,因此QPS会变的很平滑,这对于服务器来说是更友好的:
下面对排队等待模式进行测试:
- 1)为
/user/update
资源添加流控规则,QPS为10,流控效果选择配对等待,超时时间为5000ms
- 2)使用jmeter工具进行测试
启动后,所有请求均成功执行:
- 3)Sentinel控制台查看实时监控,QPS非常平滑,一直保持在10,超出的请求没有被拒绝,而是放入队列。因此响应时间(等待时间)会越来越长。当队列满了以后,才会有部分请求失败:
2.5 热点参数限流
上面的限流是统计访问某个资源的所有请求,判断其是否超过QPS阈值。而热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值。
2.5.1 全局参数限流
全局参数限流即对所有参数一视同仁,每个参数值都不能超过QPS阈值。
例如有一个根据id查询用户的接口:
@SentinelResource("queryById")
@GetMapping("/queryById")
public String queryById(String id) {String msg = "查询用户成功,id=" + id;System.out.println(msg);return msg;
}
注意:热点参数限流对默认的SpringMVC资源无效,因此需要利用@SentinelResource
注解标记资源。
然后为queryById
资源添加热点规则,对其0号参数(即第1个参数)做统计,每1秒相同参数值的请求数不能超过5
使用jmeter工具进行测试,设置QPS=10:
测试/user/queryById?id=101
:
测试/user/queryById?id=102
:
测试结果符合预期。
2.5.2 热点参数限流
在实际开发中,可能存在一些热点参数,例如名人ID。这些热点参数的QPS要高一些,那就需要配置热点参数限流的高级选项。
下面对热点参数限流进行测试:
- 1)为
/user/queryById
资源添加热点规则,实现以下需求- 参数id=101,每1秒请求量不超过5
- 参数id=102,每1秒请求量不超过10
- 其余参数id,每1秒请求量不超过2
- 2)使用jmeter工具进行测试,设置QPS=12
- 3)测试
/user/queryById?id=101
- 4)测试
/user/queryById?id=102
- 5)测试
/user/queryById?id=103
测试结果符合预期。
…
本节完,更多内容请查阅分类专栏:微服务学习笔记
感兴趣的读者还可以查阅我的另外几个专栏:
- SpringBoot源码解读与原理分析
- MyBatis3源码深度解析
- Redis从入门到精通
- MyBatisPlus详解
- SpringCloud学习笔记