写点什么

SpringCloud 从入门到精通 17---Sentinel 降级 / 热点规则

用户头像
Felix
关注
发布于: 2021 年 02 月 03 日

降级规则

以下介绍来自官方文档:

除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

熔断策略目前有以下几种:

慢调用比例:

选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

这个策略主要应用于对接口平均响应时间的管控.比如访问/testC接口,假如每秒请求数大于5,并且接口的平均响应时间大于我们设定的值,那么在接下来的时间窗口内,访问此接口就会被熔断.这些限制均来源于官方文档


为了模拟此效果,我们修改/testC接口的线程睡眠时间为 800ms

@GetMapping(value = "/testC")    public CommonResult testC(){        try {            TimeUnit.MILLISECONDS.sleep(800);            return CommonResult.success("TEST C");        } catch (InterruptedException e) {            return CommonResult.success("TEST C TIME OUT");        }    }
复制代码

然后新增一个降级策略


此配置的意思,就是针对/testC接口,假如每秒的访问量超过5个,并且接口的平均响应时间大于200ms(比我们设置的 800ms肯定大),那么在接下来的1S内,此接口被熔断,过了1S的窗口期,会接收1个请求,如果该请求响应时间大于200ms,那么接口仍被熔断1S,如果该请求响应时间小于200ms,那么接口将不再熔断.上面配置好以后,我们使用jmeter/testC接口进行压测,开启 30个线程同时访问/testC接口,以触发熔断


启动压测后,通过web界面访问/testC接口,可以发现,接口处于熔断状态

但是如果停止压测,在 1S 后,接口不再熔断


异常比例:

当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

很好理解,当我们访问一个接口,如果接口在单位时间内异常的比例超过我们设定的值,那么服务就会被熔断,过了时间窗口期以后,会接受一个请求,加入接口不再抛出异常,则服务恢复,否则,服务会进入下一个时间窗口的熔断.

我们新增一个/testD接口,并手动制造异常

@GetMapping(value = "/testD")    public CommonResult testD(){        int a = 100/0;        return CommonResult.success("TEST D");    }
复制代码

此接口中,使用 100 除以 0,一定会抛出异常

接下来,针对 /testD新建一个降级规则

此规则表示,在1S内,如果该接口的异常比例超过50%那么就会被熔断5S,过了5S以后,再次请求接口,肯定仍然会有异常,所以我们会看到错误界面,服务被熔断5S,再次请求后,则会看到服务的限流信息

我们快速访问http://localhost:8010/testD,会发现服务由刚开始的错误信息,变为限流信息


然后等待5S,访问界面,服务不再被限流,而是显示错误界面,紧接着,再访问一次,就又触发了限流,显示限流信息


异常数:

当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

这个与上面的异常比例比较类似,大家可以自己进行尝试

1S内接口超过5个异常,那么就会触发熔断.

热点规则

何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:


商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制

用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制


热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。


热点规则常用于对某个参数进行限制,或者对参数的值进行例外规则设置.举例来说,我们创建了一个接口/testE,可选传递参数为p1 p2,我们可以针对接口中的 p1参数进行限流,当然,也可以更细粒度的对p1的值进行限流.我们新建一个接口/testE

@GetMapping(value = "/testE")@SentinelResource(value = "testE",blockHandlerClass = {FelixBlockHandler.class},blockHandler = "felixBlockHandler")public CommonResult testE(@RequestParam(value = "p1",required = false) String p1,                          @RequestParam(value = "p2",required = false) String p2){    return CommonResult.success("热点限流:testE-----p1:"+p1+"----p2:" + p2);}
复制代码

这里引入了@SentinelResource注解,设置了资源名为testE,触发限流规则后,可由FelixBlockHandler.class中的felixBlockHandler来自定义返回的内容

package com.felix.sentinel.handler;
import com.alibaba.csp.sentinel.slots.block.BlockException;import com.felix.common.result.CommonResult;
public class FelixBlockHandler { public static CommonResult felixBlockHandler(String p1,String p2,BlockException ex){ return new CommonResult(50000,"服务器开小差了","failed",null); }}
复制代码
需要注意,这里的felixBlockHandler的参数和返回值必须与/testE接口函数的参数返回值保持一致,否则当触发限流的时候,自定义的限流无效

然后,针对testE资源新建一个热点规则的限流


这里我们针对p1参数进行限流,所以设置参数的索引为0,限流模式仅能为QPS,单机阈值我们设置为1,也就是在 1S内,对于/testE接口的访问中,如果带有p1参数,那么就限制访问速率为 1QPS

接下来我们对p1的值进行更细粒度的限流,在热点限流中编辑test

点开高级选项,设置参数类型为java.lang.String,参数值为1,限流阈值为200

这里的意思就是当访问/testE接口时,如果带有p1的参数,就显示QPS1,但是如果p1参数的值为1的时候,则限制QPS200,设置完之后,我们进行如下测试,首先访问http://localhost:8010/testE?p1=123&p2=456,很明显,当QPS大于1的时候,就会触发限流

但是,如果我们把p1的参数设置为1的时候,即使快速刷新界面,也不会再触发限流了http://localhost:8010/testE?p1=1&p2=456


发布于: 2021 年 02 月 03 日阅读数: 50
用户头像

Felix

关注

还未添加个人签名 2020.12.24 加入

还未添加个人简介

评论

发布
暂无评论
SpringCloud 从入门到精通17---Sentinel降级/热点规则