Sentinel 流量控制
携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情
可以去查询官方文档sentinelguard.io/zh-cn/docs/…
1. 簇点链路
请求进入微服务的时候,按照 DispatcherServlet ——> Controller ——> Service ——> Mapper这个调用链访问。这个调用链路就叫做簇点链路。簇点链路中被监控的每一个接口就是一个资源。
默认情况下 Sentinel 会监控 SpringMVC 的每一个端点(Endpoint,就是 Controller 中的方法),因此 SpringMVC 的每个端点就是调用链路中的一个资源。
这些便是端点
接下来学习的流控、熔断等都是针对簇点链路中的资源来设置的。
2. 流控模式
接下来我们就使用 Sentinel + JMeter 来进行学习
流控模式是通过限定或控制对应资源的 QPS 从而达到流量控制的效果。
QPS:Queries Per Second意思是“每秒查询率”,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
在 Sentinel 中,当调用该资源的 QPS 达到阈值的时候,进行限流
在 Sentinel 控制台添加限流规则时,点击高级选择,可以选择三种流控模式:
- 直连:统计当前资源的请求,触发阈值时,对当前资源进行限流,也是默认模式
- 关联:统计与当前资源相关联的另一个资源,触发阈值时,对当前资源限流
- 链路:统计从指点链路访问到本资源的请求,触发阈值时,对指定链路限流(对某个路径的资源限流)
2.1 直接模式
-
直连模式
统计当前资源的请求,超出阈值的请求直接拦截并报错。
-
操作步骤:
我们将对应的资源开启,在 Sentinel 中设置。
点击对应资源后面的流控按钮,可以弹出表单,如下:
在表单中填写限流规则,如下:
单机阈值就是 QPS。这里的意思就是 每秒只能有5个资源允许访问。当每秒的请求超出单机阈值的时候会被拦截并报错。
可以通过 JMeter 进行测试和在控制台看到对应的请求成功和请求失败的比例
2.2 关联模式
-
关联模式:
统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流。
为了方便理解我们举个例子:我出去给店揽客,客人太多店里坐不下,老板叫我少揽点客人。饭店触发阈值,对我进行限流。
当关联的资源达到阈值,就限流自己。
-
配置规则:
当“饭店”满 5 人的时候对“我”的请求进行限流
-
使用场景:购买页面中有俩个重要的接口,一个是读取商品概览,一个是读取详细商品信息。在高并发业务场景中,两个接口都会占用资源。如果商品概览的访问量过大,就会影响详细商品信息的性能。如果业务中我们希望读取详细商品信息的优先级高于商品概览,就可以使用关联模式。当读取详细商品的请求多,就限制读取商品概览。
-
总结:当满足 两个有竞争关系的资源 和 一个优先级高,一个优先级低 这两个条件的任意一个都可以使用关联模式。
-
需求说明
-
在OrderController新建两个端点:/order/query和/order/update,无需实现业务
-
配置流控规则,当/order/ update资源被访问的QPS超过5时,对/order/query请求限流
1)定义/order/query端点,模拟订单查询
@GetMapping("/query") public String queryOrder() { return "查询订单成功"; }2)定义/order/update端点,模拟订单更新
@GetMapping("/update") public String updateOrder() { return "更新订单成功"; }重启服务,查看sentinel控制台的簇点链路:
3)配置流控规则
对哪个端点限流,就点击哪个端点后面的按钮。我们是对订单查询/order/query限流,因此点击它后面的按钮:
在表单中填写流控规则:
4)在Jmeter测试
选择《流控模式-关联》:
可以看到1000个用户,100秒,因此QPS为10,超过了我们设定的阈值:5
查看http请求:
请求的目标是/order/update,这样这个断点就会触发阈值。
但限流的目标是/order/query,我们在浏览器访问,可以发现:
确实被限流了。
-
2.3 链路模式
-
链路模式:
只针对从指定链路访问到本资源的请求做统计,判断是否超过阈值。
为了方便理解我们举个例子:我从街上招揽的顾客去饭店要等位,老板的亲戚去饭店不用等位。从“我”这个链路访问“饭店”这个资源需要做限制,从“老板”这个链路访问“饭店”这个资源不需要做限制。
从指定链路访问资源就限流。
-
配置规则:
从“我”这个链路访问“饭店”这个资源的请求每秒超过5个就限流
-
实战案例
需求:有查询订单和创建订单业务,两者都需要查询商品。针对从查询订单进入到查询商品的请求统计,并设置限流。
步骤:
-
在OrderService中添加一个queryGoods方法,不用实现业务
-
在OrderController中,改造/order/query端点,调用OrderService中的queryGoods方法
-
在OrderController中添加一个/order/save的端点,调用OrderService的queryGoods方法
-
给queryGoods设置限流规则,从/order/query进入queryGoods的方法限制QPS必须小于2
实现:
1)添加查询商品方法
在order-service服务中,给OrderService类添加一个queryGoods方法:
public void queryGoods(){ System.err.println("查询商品"); }2)查询订单时,查询商品
在order-service的OrderController中,修改/order/query端点的业务逻辑:
@GetMapping("/query") public String queryOrder() { // 查询商品 orderService.queryGoods(); // 查询订单 System.out.println("查询订单"); return "查询订单成功"; }3)新增订单,查询商品
在order-service的OrderController中,修改/order/save端点,模拟新增订单:
@GetMapping("/save") public String saveOrder() { // 查询商品 orderService.queryGoods(); // 查询订单 System.err.println("新增订单"); return "新增订单成功"; }4)给查询商品添加资源标记
默认情况下,OrderService中的方法是不被Sentinel监控的,需要我们自己通过注解来标记要监控的方法。
给OrderService的queryGoods方法添加@SentinelResource注解:
@SentinelResource("goods") public void queryGoods(){ System.err.println("查询商品"); }链路模式中,是对不同来源的两个链路做监控。但是sentinel默认会给进入SpringMVC的所有请求设置同一个root资源,会导致链路模式失效。
我们需要关闭这种对SpringMVC的资源聚合,修改order-service服务的application.yml文件:
spring: cloud: sentinel: web-context-unify: false # 关闭context整合重启服务,访问/order/query和/order/save,可以查看到sentinel的簇点链路规则中,出现了新的资源:
5)添加流控规则
点击goods资源后面的流控按钮,在弹出的表单中填写下面信息:
只统计从/order/query进入/goods的资源,QPS阈值为2,超出则被限流。
6)Jmeter测试
选择《流控模式-链路》:
可以看到这里200个用户,50秒内发完,QPS为4,超过了我们设定的阈值2
一个http请求是访问/order/save:
运行的结果:
完全不受影响。
另一个是访问/order/query:
运行结果:
每次只有2个通过。
-
2.4 总结
流控模式有哪些?
- 直接:对当前资源限流
- 关联:高优先级资源触发阈值,对低优先级资源限流。
- 链路:阈值统计时,只统计从指定资源进入当前资源的请求,是对请求来源的限流