写点什么

SpringCloud Alibaba Sentinel 限流详解

作者:牧小农
  • 2022 年 5 月 29 日
  • 本文字数:4045 字

    阅读完需:约 13 分钟

SpringCloud Alibaba Sentinel 限流详解

点赞再看,养成习惯,微信搜索【牧小农】关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友。项目源码地址:公众号回复 sentinel,即可免费获取源码

熔断规则

在上一篇文章中我们讲解了流控规则的使用和介绍Sentinel流控规则,今天我们给大家讲解sentinel更多样化的讲解以及流量控制。


官方文档:https://sentinelguard.io/zh-cn/docs/circuit-breaking.html


在面对调用链路中不稳定的资源如何保证高可用?在微服务中一个服务通常会调用其他的模块,可能是服务内的某个应用也有可能是另外的一个远程服务,数据库或者其他 API 调用。比如我们在支付的时候会调用(某付宝、某信、某联)提供的 API,在查询订单我们会调用数据库连接,这些依赖的服务有可能会存在系统不稳定的情况,如果依赖的服务出现了不稳定的情况,请求响应时间过长,线程资源产生堆积,可能最终会耗尽服务的资源,导致服务变的不可用,这个时候 熔断降级 是保证服务高可用的重要措施之一。



如今的微服务都是分布式,有很多服务组成,不同服务之间互相调用,有着比较复杂的调用链路,在上面我们只是模拟绘画了支付操作,在实际的链路调用过程中会有着放大效果,如果某一环不稳定,可能会形成 蝴蝶效应 最终导致整个链路响应时间过长,甚至不可用,所以如果当我们的服务出现 不稳定且没有强依赖服务 调用的时,可以进行熔断降级,暂时限制不稳定的调用,避免影响整体服务。


熔断策略:

sentinel提供了三种熔断策略



  • 慢调用比例: 选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(最大响应时间),如果请求响应时间大于该值则认为慢调用,当统计时长内请求数 大于 最小请求数,且慢调用比例大于阈值,在熔断时长内的请求会被自动熔断,超过熔断时长进入半恢复状态(HALF_OPEN),如果下一个请求响应时间 小于 慢调用比例 RT 结束熔断,否则再次熔断。

  • 异常比例: 当统计时长内请求数 大于 最小请求数,且异常比例大于设定的阈值,在熔断时间内请求自动熔断,超过熔断时长进入半恢复状态(HALF_OPEN),如果下一个请求成功,结束熔断,否则再次熔断,异常比例阈值范围(0.0-1.0)代表百分比。

  • 异常数: 当统计时长内异常数 大于 阈值,自动进行熔断,超过熔断时长进入半恢复状态(HALF_OPEN),如果下一个请求成功,结束熔断,否则再次熔断。


熔断状态:



热点参数规则的核心属性:


熔断策略 - 慢调用比例

选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(最大响应时间),如果请求响应时间大于该值则认为慢调用,当统计时长内请求数 大于 最小请求数,且慢调用比例大于阈值,在熔断时长内的请求会被自动熔断,超过熔断时长进入半恢复状态(HALF_OPEN),如果下一个请求响应时间 小于 慢调用比例 RT 结束熔断,否则再次熔断。



如果我们一秒钟请求的数量大于 5 且 RT(最大响应时间)大于我们设置的比例阈值的时候,触发熔断策略,比如我们有 8 个请求在一秒中进来,有 5 个慢调用,比例阈值设置为 0.1,这个时候我们满足(QPS > 5 且 RT > 比例阈值),进入下一步熔断策略,触发熔断器。


熔断器的内部使用的是断路器,这个好比我们做核酸,本来一栋一栋下去做,如果服务或者检测机器蹦了,通知你暂时不要下来,当机器恢复了,再通知你下来做,这个就类似我们的断路器。



案例演示:


    @GetMapping("/fuse")    public String fuse(){        try {            TimeUnit.SECONDS.sleep(3);        } catch (InterruptedException e) {            e.printStackTrace();        }        return "hello fuse";    }
复制代码


设置我们的熔断策略,如果 QPS>5 请求 RT>250 且大于比例阈值触发熔断



通过JMeter测试,1 秒钟发起 10 个线程请求,此时就会触发熔断效果,停止测试以后,10 秒钟恢复正常



当我们启动线程之后,再去访问 fuse 接口,可以看到被熔断了,那么当我们停止线程之后,十秒之后去访问,就可以正常访问


熔断策略 - 异常比例

当统计时长内请求数 大于 最小请求数,且异常比例大于设定的阈值,在熔断时间内请求自动熔断,超过熔断时长进入半恢复状态(HALF_OPEN),如果下一个请求成功,结束熔断,否则再次熔断,异常比例阈值范围(0.0-1.0)代表百分比。异常降级仅仅只针对业务异常,对于sentinel本身的异常不生效。



测试:


    @GetMapping("/exptoin")    public String exptoin(Integer id){        if(id != null && id > 1){            throw new RuntimeException("异常比例测试");        }        return "exptoin test";    }
复制代码



接下来我们用 JMeter 进行测试,设置 Http 请求地址:http://localhost:8006/exptoin?id=5 当启动 JMeter 的时候,会触发熔断,这个时候我们 1 秒钟发送 10 个请求超过了最小请求数,同事超过了阈值,满足两个条件,当熔断时间结束 以后恢复正常


熔断策略 - 异常数

当统计时长内异常数 大于 阈值,自动进行熔断,超过熔断时长进入半恢复状态(HALF_OPEN),如果下一个请求成功,结束熔断,否则再次熔断。



测试代码:


    @GetMapping("/exptoin/num")    public String exptoinNum(Integer id){        if(id != null && id > 1){            throw new RuntimeException("异常数测试");        }        return "exptoinNum test";    }
复制代码


设置异常数策略,当 1 秒钟内请求超过 5 并且异常数大约 5 个的时候触发熔断




热点规则

官网文档:https://sentinelguard.io/zh-cn/docs/parameter-flow-control.html


什么是热点规则?热点我们很好理解,就是很火的东西在程序中可以理解成频繁访问的数据,那么有时候我们系统通缉你某个热点数据中访问频次最高的 前几个数据对其进行限制访问。


例如在秒杀系统中,某一款商品或者某几款商品,要定点秒杀,我们可以以商品 ID 为参数,在一定时间内对其进行限流


又或者如果某一个用户频繁的去访问我们系统,我们也可以针对于用户 ID 或者 IP 进行限制。


热点规则会统计入参参数中的热点数据,根据配置的限流阈值和模式,对启动的热点数据进行限流也就是流量控制。



在上图中我们携带了 是三个参数(axb\abc\xs)等,我们在sentinel中设置热点限流,我们设置的 QPS 为 5,注意:该模式只支持 QPS 限制,如果我们的 axb 参数,命中了我们的规则,那么该请求携带的参数就会被限流。



在使用热点规则的时候,我们需要配合对应的@SentinelResource注解进行使用,才能够达到更加细粒度的流控规则。@SentinelResource


  • value:代表资源名称,必填,通过 name 找到对应的规则

  • blockHandler: blockHandler 对应处理 BlockException 的方法名称,可选项,访问范围为 public,返回类型需要和原方法匹配,并且在最后一需要添加BlockException类型的参数



测试代码:


    @GetMapping("/hotTest")    @SentinelResource(value = "hotTest")    public String testHotKey(@RequestParam(value = "v1",required = false) String v1,                             @RequestParam(value = "v2",required = false)String v2){        return "热点规则 -  热点:";    }
复制代码



在这里我们要注意,我们需要配置的是不带斜杠的资源名称,这个才是我们需要配置的项目



这个时候我们传入参数 http://localhost:8006/hotTest?v1,不停的刷新浏览器,这个时候会超过阈值,那么下面就会出现限流



但是,这个报错信息不是很友好,一般人根本不知道啥意思,我们可以使用@SentinelResource注解提供的另外一个参数blockHandler,这个参数是可以指定当出现异常时的处理方法,操作如下:


    @GetMapping("/hotTest")    @SentinelResource(value = "hotTest",blockHandler = "handler_hot")    public String testHotKey(@RequestParam(value = "v1",required = false) String v1,                             @RequestParam(value = "v2",required = false)String v2){
if("5".equals(v1)){ throw new RuntimeException("报告有bug!!!"); } return "热点规则 - 热点:"; } //处理异常方法,方法签名要和对应的接口方法保持一致 public String handler_hot(String v1, String v2, BlockException exception){ return "请求过于频繁,请稍后再试....."; }
复制代码


重新添加热点规则后,再去频繁的去访问,效果如下:



例外项数目



热点规则除了上述的基础使用外,还有例外项的操作,例外项参数可以达到更加细粒度的控制,比如我们在当前的案例中,目前 v1 参数在访问时超过阈值则会被限流,当时如果我们想通过参数 v1 等于具体的值的时候,来出发不同的流控效果时,改怎么操作呢?


比如我想要让 v1 等于 2 的时候,阈值达到 50,其他的规则走上面的规则。



如果当前 v1 的值为 2 的时候,会走例外项里面的设置,也就是 50 的阈值,如果不是 2 会走普通的阈值规则,通过下图我们可以看到如果为 2 的值,无论我们点击多少次,都不会提示我们请求过于频繁。


系统规则

sentinel系统自适应限流是从整体维度对应用入口流量进行控制,结合应用的 load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,来让系统入口流量和系统的负载达到一个平衡,让系统尽可能的在面对高并发访问的同时保证系统整体的稳定。


系统保护是应用整体,所以不具备更细粒度的操作,只针对于入口流量有效。



系统规则支持的模式:



  • LOAD 自适应: 针对于 linxu/unix 机器有效,系统 load(一分钟平均负载)作为启发指标,进行自适应系统保护。

  • RT:单台机器上所有的入口流量平均 RT 达到阈值时,触发系统保护,单位为毫秒

  • 线程数: 单台机器上所有入口流量的并发线程数达到阈值触发系统保护

  • 入口 QPS: 单台机器上所有入口流量的 QPS 达到阈值触发系统保护

  • CPU 使用率: 当系统 CPU 使用率超过阈值时触发系统保护(取值范围:0.0 - 1.0)


演示:


通过入口 QPS 来进行测试,直接设置规则



最后测试效果不管现在我们访问那个接口只要超过阈值就会被限流


总结

到这里我们限流策略就讲完了,其实并不复杂,我们需要了解其中每个规则如何使用,效果是怎样的,最好是自己动手试一试,会更有成就感。


我是牧小农,怕什么真理无穷,进一步有进一步的欢喜,大家加油

发布于: 刚刚阅读数: 5
用户头像

牧小农

关注

业精于勤荒于嬉,行成于思毁于随。 2019.02.13 加入

公众号【牧小农】

评论

发布
暂无评论
SpringCloud Alibaba Sentinel 限流详解_sentinel_牧小农_InfoQ写作社区