在之前的内容中,我们介绍了Sentinel相关信息以及怎么把Sentinel整合到我们的项目中,接下来我们要开始学习Sentinel的各种规则。
Sentinel 流控规则
- 资源名称: 唯一名称。默认请求路径
- 针对来源: Sentinel 可以针对调用者进行限流,填写微服务名称,默认defalut(不区分来源)。
- 阈值类型/单机阈值:
1、QPS(每秒的请求数量): 当调用该api的QPS达到阈值的时候,进行限流
2、线程数: 当调用该api的线程数达到阈值时候,进行限流 - 是否集群: 不需要集群
- 流控模式:
1、直接,api达到限流条件时,直接限流
2、关联,当关联资源达到阈值时,就限流自己
3、链路:只记录指定链路上的流量(指定资源从人口资源进来的流量,如果达到阈值,就进行限流) - 流控效果:
1、快速失败:直接失败,抛异常
2、Warm Up:根据CodeFactory(冷加载因子,默认3)的值,阈值/codeFactory,经过预热时长,才达到设置的QPS阈值
3、排队等待:匀速排队,让请求以均匀的速度通过,阈值类型必须设置为QPS,否则无效
流控模式
我们测试验证一下这些规则:
1、表示1s钟内查询1次就是成功,若超过次数1,就直接快速失败,报默认错误。
我们快速点击访问: http://localhost:8004/testA
结果:
2、当关联资源/testB的QPS阈值超过1,就限流/testA
我们测试验证一下:
上面这个30 和 500 分别 30个线程每次间隔0.5秒访问一次testB.
然后点击访问: http://localhost:8004/testA
3、链路和关联类似,多个请求调用了同一个微服务。
流控效果
1、直接失败,抛出异常 Blocked by Sentinel (flow limiting)
2、warm Up(限流 冷启动): 当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。
详细内容请看: https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81—%E5%86%B7%E5%90%AF%E5%8A%A8
阀值为10+预热时长设置5秒。
系统初始化的阀值为10 / (CodeFactory=3) 约等于3,即阀值刚开始为3;然后过了5秒后阀值才慢慢升高恢复到10。
测试验证: 多次点击 http://localhost:8004/testB
应用场景: 秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。
3、排队等待
它的中心思想是,以固定的间隔时间让请求通过。当请求到来的时候,如果当前请求距离上个通过的请求通过的时间间隔不小于预设值,则让当前请求通过;否则,计算当前请求的预期通过时间,如果该请求的预期通过时间小于规则预设的 timeout 时间,则该请求会等待直到预设时间到来通过(排队等待处理);若预期的通过时间超出最大排队时长,则直接拒接这个请求。这种方式适合用于请求以突刺状来到,这个时候我们不希望一下子把所有的请求都通过,这样可能会把系统压垮;同时我们也期待系统以稳定的速度,逐步处理这些请求,以起到“削峰填谷”的效果,而不是拒绝所有请求。例如,如果系统使用 Apache RocketMQ 来收发消息,系统在某个时间突然收到大量消息。我们希望以固定的速率来处理消息,而不是一下子拒绝这些消息。这个时候可以使用匀速器,也就是给消息排队。效果如下所示:
匀速排队,让请求以均匀的速度通过,阀值类型必须设成QPS,否则无效。/testA每秒1次请求,超过的话就排队等待,等待的超时时间为2000毫秒。
测试验证:
熔断规则
Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,
让请求快速失败,避免影响到其它的资源而导致级联错误。 当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。
详情地址: https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
在SentinelServiceController类中新增方法:
@GetMapping("/testC")
public String testC() {
try {
// 调用等待2s钟
Thread.sleep(1000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("testc");
return "testC";
}
慢调用比例
1、当请求数大于5以后,如果请求的响应时间大于200ms的请求超过20%,则熔断10s。
RT 平均响应时长:如果1s内持续进入5个请求,对应时刻的平均响应时间(秒)均超过(count,以ms为单位),那么在接下的时间窗口之内,对这个方法的调用都会自动地熔断(抛出DefradeException)。注意Sentinel默认统计的RT上限是4900ms,超出此阈值的都会算作4900ms。
我们通过jmeter压测一下,jmeter我们之前的章节中是有将过的。
可以看到此时已经出现服务降级了。我们停止jemter压测,再次访问
此时有可以获取到值了。
结论:
按照上述配置,永远一秒钟打进来10个线程(大于5个了)调用testC,我们希望200毫秒处理完本次任务,
如果超过200毫秒还没处理完,在未来1秒钟的时间窗口内,断路器打开(保险丝跳闸)微服务不可用,后续我停止jmeter,没有这么大的访问量了,断路器关闭,微服务恢复OK。
异常比例数
异常比例:当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比例值超过阈值之后,资源进入降级状态,即在接下的时间窗口(统计时长)之内,对这个方法的调用都会自动的返回异常。
1、请求数量大于5,异常请求数量比例大于20%,熔断10s
我们修改SentinelServiceController类:
新增方法
@GetMapping("/testD")
public String testD() {
System.out.println("testD 出现异常");
int i = 5/0;
return "testC";
}
我们先调用 http://localhost:8004/testD 一下,发现接口返回异常信息:
我们通过jemter 压测:
再到调用 : http://localhost:8004/testD
此时出现服务降级了。
结论:
单独访问一次,调一次错一次;开启jmeter后,直接高并发发送请求,多次调用达到我们的配置条件了。断路器开启微服务不可用了,不再报错error而是服务降级了。
异常数
当资源1s的异常数目超过阈值之后就会进行熔断。
1、请求数量大于5,异常数量超过1个以上,熔断10是。
修改SentinelServiceController类:
新增方法:
@GetMapping("/testE")
public String testE() {
int i = 5/0;
return "testE";
}
测试 http://localhost:8004/testE
再次请求: http://localhost:8004/testE
此时出现服务降级了。
结论:
第一次访问绝对报错,因为除数不能为零,我们看到error窗口,但是达到1次报错后,进入熔断后降级。
热点key限流
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。
比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。
详细信息: https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81
修改 SentinelServiceController类:
新增方法:
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey")
public String testHotKey(@RequestParam(value = "pa1",required = false) String pa1,
@RequestParam(value = "pa2",required = false) String pa2){
System.out.println("pa1: "+ pa1+":" +"pa2: " + pa2);
return "testHotKey";
}
这个@SentinelResource 注解和HystrixCommand 类似。
1、对第一个参数进行限流操作,每秒只能通过1个。
快速点击测试: http://localhost:8004/testHotKey?pa1=111
测试: http://localhost:8004/testHotKey?pa1=111&pa2=2222
测试:http://localhost:8004/testHotKey?pa2=2222
我们看到,上面的报错信息不是很友好,这个@SentinelResource和Hystrix 一样,也可以自定义降级策略。我们修改下代码:
我们在测试一下:
上述案例演示了第一个参数pa1,当QPS超过1秒1次点击后马上被限流。我们期望pa1参数当它是某个特殊值时,它的限流值和平时不一样假如当pa1的值等于444时,它的阈值可以达到200。
记得点击添加按钮。
我们测试一下: http://localhost:8004/testHotKey?pa1=222
我们在测试一下: http://localhost:8004/testHotKey?pa1=444
当pa1等于444的时候,阈值变为200,当pa1不等于444的时候,阈值就是平常的1。
系统规则
系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。
系统规则支持以下的模式:
- Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。
- CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
- 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
当CPU利用率超过4%,就不允许请求访问该服务器,以防止系统崩溃。
授权规则
很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源访问控制(黑白名单控制)的功能。来源访问控制根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通。
详细信息: https://github.com/alibaba/Sentinel/wiki/%E9%BB%91%E7%99%BD%E5%90%8D%E5%8D%95%E6%8E%A7%E5%88%B6