Sentinel流控规则整理
注:Sentinel的监控页面一开始是没有东西,需要对监控的服务发起请求后才会出现
流量控制(flow control)
- 原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性;
两种规则
- 基于统计并发线程数的流量控制
并发数控制用于保护业务线程池不被慢调用耗尽
Sentinel 并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目);
如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离;
- 基于统计QPS的流量控制
当 QPS 超过某个阈值的时候,则采取措施进行流量控制;
控制面板
-
资源名:唯一名称,默认请求路径
-
针对来源:
Sentinel
可以针对调用者进行限流,填写微服务名,指定对哪个微服务进行限流 ,默认default
(不区分来源,全部限制) -
阈值类型/单机阈值:
-
QPS(每秒钟的请求数量):当调用该接口的QPS达到了阈值的时候,进行限流;
-
线程数:当调用该接口的线程数达到阈值时,进行限流
-
-
是否集群:不需要集群
-
流控模式:
-
直接:接口达到限流条件时,直接限流
-
关联:当关联的资源达到阈值时,就限流自己
-
链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就可以限流)[api级别的针对来源]
-
-
流控效果
-
快速失败:直接失败,就异常
-
Warm Up:根据
codeFactor
(冷加载因子,默认为3)的值,即请求 QPS 从threshold / 3
开始,经预热时长逐渐升至设定的 QPS 阈值 [https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81---%E5%86%B7%E5%90%AF%E5%8A%A8#%E6%A6%82%E8%BF%B0]
-
直接快速失败的效果:
当请求A过来访问该接口,该请求处理的很慢,还没有返回数据;此时请求B也过来访问该接口,这个时候处理请求B需要额外开启一个线程,请求B则会报错;
效果如下:
流控模式
- 直接模式
Sentinel的流控模式代表的流控的方式,默认【直接】;
上面的/testA接口的流控,QPS单机阀值为1,代表每秒请求不能超出1,要不然就做流控处理,处理方式直接调用失败;
调用/testA,慢一点请求,正常返回;快速请求几次,超过阀值;接口返回了Blocked by Sentinel (flow limiting),代表被限流了;
- 关联模式
设置效果:当关联资源/testB的QPS阈值超过1时,就限流/testA的Rest的访问地址,当关联资源到资源阈值后限制配置好的资源名;
关联通俗点说就是,当关联的资源达到阀值,就限流自己;
应用场景: 比如支付接口达到阈值,就要限流下订单的接口,防止一直有订单
链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流;它的功能有点类似于针对 来源配置项,区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度 更细;
1.编写一个service
@Service public class OrderServiceImpl implements OrderService { @Override @SentinelResource(value = "getOrder", blockHandler = "handleException") public CommonResult getOrder() { return new CommonResult(0, String.valueOf(new Random().nextInt())); } public CommonResult handleException(BlockException ex) { return new CommonResult(-1, ex.getClass().getCanonicalName() + "\t服务不可用"); } }
2.在Controller声明两个方法
@Autowired private OrderService orderService; @GetMapping("/test1") public CommonResult test1() { return orderService.getOrder(); } @GetMapping("/test2") public CommonResult test2() { return orderService.getOrder(); }
注意:
从1.6.3 版本开始, Sentinel Web filter默认收敛所有URL的入口context,因此链路限流不生效;
1.7.0 版本开始(对应Spring Cloud Alibaba的2.1.1.RELEASE),官方在CommonFilter
引入了WEB_CONTEXT_UNIFY
参数,用于控制是否收敛context;将其配置为 false 即可根据不同的URL 进行链路限流; [https://github.com/alibaba/Sentinel/issues/1213]
@Configuration public class FilterContextConfig { @Bean public FilterRegistrationBean sentinelFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new CommonFilter()); registration.addUrlPatterns("/*"); // 入口资源关闭聚合 registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false"); registration.setName("sentinelFilter"); registration.setOrder(1); return registration; } }
流量效果
-
快速失败
直接拒绝(
RuleConstant.CONTROL_BEHAVIOR_DEFAULT
)方式是默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException
。这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。具体的例子参见[
Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP
)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。详细文档可以参考
[
根据codeFactor
(冷加载因子,默认为3)的值,即请求 QPS 从 threshold / 3
系统初始化的默认阈值为10 / 3,即为3,也就是刚开始的时候阈值只有3,当经过5s后,阈值才慢慢提高到10;
源码:com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController
应用场景:秒杀系统的开启瞬间,会有很多流量上来,很可能会把系统打挂,预热方式就是为了保护系统,可以慢慢的把流量放进来,慢慢的把阈值增长到设定值;
匀速排队,让请求以均匀的速度通过,阈值类型必须设置成QPS
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
源码:com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController
[