当前位置: 首页 > 科技观察

SpringCloudAlibabaSentinel限流详解

时间:2023-03-21 11:18:34 科技观察

熔断规则在上一篇文章中,我们讲解了流控规则的使用,介绍了Sentinel流控规则。今天我们就给大家讲解一下哨兵控制的更多样化的解释和流程。官方文档:https://sentinelguard.io/zh-cn/docs/circuit-breaking.html面对调用链路不稳定的资源如何保证高可用?在微服务中,一个服务通常会调用其他模块,它可能是服务中的应用程序或另一个远程服务、数据库或其他API调用。比如我们支付的时候会调用(支付宝,Xxin,Xlian)提供的API,查询订单的时候会调用数据库连接。这些依赖服务可能存在系统不稳定。如果依赖的服务在不稳定的情况下,请求响应时间过长,线程资源堆积,最终可能会耗尽服务资源,导致服务不可用。此时,熔断器降级是保证服务高可用性的重要措施之一。今天的微服务都是分布式的,由很多服务组成。不同的服务相互调用,调用环节相对复杂。上面我们只是模拟了支付操作,在实际的链接调用过程中会有放大。这样一来,如果某个链路不稳定,就可能形成蝴蝶效应,最终导致整个链路响应时间过长,甚至不可用。因此,如果我们的服务不稳定,对服务调用没有强依赖,我们可以进行熔断降级,暂时限制不稳定的调用,避免影响整体服务。熔断策略:sentinel提供了三种熔断策略:慢调用率:选择慢调用率作为阈值,需要设置允许的慢调用RT(最大响应时间),如果请求响应时间大于这个值,则为认为是慢调用,当统计时长内的请求数大于最小请求数,且慢调用占比大于阈值,熔断时长内的请求会自动断开,如果duration超过duration,会进入半恢复状态(HALF_OPEN)。如果下一个请求的响应时间小于慢调用的比例,RT将结束熔断,否则重新熔断。异常比率:当统计时间内的请求数大于最小请求数,且异常比率大于设定阈值时,请求在熔断时间内自动熔断,半恢复状态(HALF_OPEN)超过定影时间后进入。如果下次请求成功,则熔断结束,否则再次熔断,异常比例阈值范围(0.0-1.0)代表百分比。异常次数:当统计周期内异常次数大于阈值时,自动进行熔断,熔断时间超过限制则进入半恢复状态(HALF_OPEN)。Fuse状态:Fuse状态表示OPEN是打开的,拒绝所有的请求。HALF_OPEN是半开(恢复状态)。如果下一个请求成功结束熔断,否则继续熔断CLOSE。热点参数规则核心属性:属性(字段)说明默认值resource资源名称(规则的对象)所需等级熔断策略(支持慢调用率/异常率/异常号策略)所需慢调用率count慢调用ratiomode是slowcallcriticalRT(超过这个值算slowcalls);在异常比率/异常数量模式下,为对应的阈值timeWindow熔断持续时间,单位为sminRequestAmount熔断触发的最小请求数。当请求数小于该值时,即使异常比例超过阈值,也不会被熔断(1.7.0引入)5statIntervalMs统计时长(单位ms),如60*1000代表分钟级别(1.8.0引入)1000msslowRatioThreshold慢调用比例阈值,只有慢调用比例模式有效(1.8.0引入)熔断策略-慢调用比例选择以慢调用比例为阈值,需要设置允许的慢调用RT(最大响应时间)。如果请求响应时间大于这个值,则认为是慢调用。在熔断时长内的请求会自动熔断,超过熔断时长则进入半恢复状态(HALF_OPEN)。如果下一次请求的响应时间小于慢调用率RT,则熔断结束,否则重新熔断。如果我们每秒的请求数大于5,并且RT(最大响应时间)大于我们设置的比率阈值,就会触发熔断策略。比如我们一秒有8个请求进来,有5个慢调用,将ratiothreshold设置为0.1,此时遇到(QPS>5andRT>ratiothreshold),进入下一步的熔断策略,触发熔断。保险丝内部是断路器。这就像我们做核酸一样。本来,我们一个一个下去做的。如果服务或检测机跳了,我们会通知您暂时不要下来。当机器恢复时,我们会通知你去做。这就像我们的断路器。案例演示:@GetMapping("/fuse")publicStringfuse(){try{TimeUnit.SECONDS.sleep(3);}catch(InterruptedExceptione){e.printStackTrace();}返回“你好保险丝”;}Set在我们的熔断策略中,如果QPS>5请求RT>250且大于ratio阈值,则触发熔断。通过JMeter测试,1秒发起10个线程请求,此时会触发熔断效果。测试停止后,10秒后恢复正常。当我们启动线程,然后访问熔断接口,可以看到熔断了,然后停止线程,十秒后访问,就可以正常访问了。熔断策略-异常比率当统计时间内的请求数大于最小请求数,且异常比率大于设定阈值时,请求在熔断时间内自动熔断,进入半恢复超过熔断时间后的状态(HALF_OPEN)。如果下次请求成功,则结束熔断,否则再次熔断,异常比率阈值范围(0.0-1.0)表示百分比。异常降级只针对业务异常,对sentinel自身的异常不生效。测试:@GetMapping("/exptoin")publicStringexptoin(Integerid){if(id!=null&&id>1){thrownewRuntimeException("异常比率测试");}返回“exptoin测试”;接下来,我们使用JMeter进行测试,设置Http请求地址:http://localhost:8006/exptoin?id=5当JMeter启动时,会触发一个熔断器。此时我们每秒发送10个请求,超过最小请求数,同事超过阈值满足两个条件,熔断时间结束后恢复正常。熔断策略-异常次数当统计周期内的异常次数大于阈值时,会自动进行熔断,超过熔断时长后进入半恢复状态(HALF_OPEN)。如果下一次请求成功,则熔断结束,否则重新启动熔断。测试代码:@GetMapping("/exptoin/num")publicStringexptoinNum(Integerid){if(id!=null&&id>1){thrownewRuntimeException("异常数测试");}返回“exptoinNum测试”;}设置异常个数策略,当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注解来实现更细粒度的流控规则。@SentinelResourcevalue:表示资源名称,必填,通过名称可以找到对应的规则。blockHandler:blockHandler对应处理BlockException的方法名,可选,访问范围是public,返回类型需要和原方法匹配,最后需要加一个BlockException类型的参数。测试代码:@GetMapping("/hotTest")@SentinelResource(value="hotTest")publicStringtestHotKey(@RequestParam(value="v1",required=false)Stringv1,@RequestParam(value="v2",required=false)Stringv2){return"热点规则-热点:";}这里需要注意的是,我们需要配置的是没有斜杠的资源名称,这是我们需要配置的项目。这个时候我们传入参数http://localhost:8006/hotTest?v1,不断刷新浏览器。这个时候会超过阈值,然后下面会有一个限流。但是,这个错误信息并不是很友好,大多数人根本不知道它是什么意思。我们可以使用@SentinelResource注解提供的另一个参数blockHandler。该参数可以指定发生异常时的处理方式。操作如下:@GetMapping("/hotTest")@SentinelResource(value="hotTest",blockHandler="handler_hot")publicStringtestHotKey(@RequestParam(value="v1",required=false)Stringv1,@RequestParam(value="v2",required=false)Stringv2){if("5".equals(v1)){thrownewRuntimeException("报告中有错误!!!");}return"热点规则-热点:";}//处理异常的方法,方法签名与对应的接口方法一致}重新添加热点规则后,去frequent效果如下:异常个数:除了上述热点规则的基本使用外,还有对异常的操作。异常的参数可以实现更细粒度的控制。比如我们现在的情况,当前的v1参数在访问超过阈值的时候,就会限流。那时候如果我们想通过参数v1等于一个特定的值来触发不同的流控效果,应该怎么改呢?比如我要v1等于2时,阈值达到50,其他规则按照上面的规则。如果v1的当前值为2,则遵循异常中的设置,即阈值50。如果不为2,则遵循正常的阈值规则。从下图中我们可以看到,如果是2,那么无论我们点击多少次,都不会提示我们请求过于频繁。系统规则Sentinel系统自适应限流是从全局维度控制应用入口流量,结合应用负载、CPU使用率、整体平均RT、入口QPS和并发线程数等几个维度的监控指标,通过自适应流量控制策略用于在系统入口流量和系统负载之间取得平衡,使系统在尽可能面对高并发访问的同时保证系统的整体稳定性。系统保护是作为一个整体来应用的,所以它没有更细粒度的操作,只对入口流量有效。系统规则支持的模式:LOAD自适应:对linxu/unix机器有效,系统负载(一分钟平均负载)作为自适应系统保护的启发式指标。RT:当单机所有入口流量的平均RT达到阈值时,触发系统保护,单位毫秒。线程数:单机所有入口流量的并发线程数达到触发系统保护的阈值。IngressQPS:单机所有Ingress流量的QPS达到触发系统保护的阈值。CPU占用率:当系统CPU占用率超过阈值(取值范围:0.0-1.0)时触发系统保护。演示:通过入口QPS测试,直接设置规则;只要我们现在访问的接口超过阈值,最终的测试效果就会受到限制。综上所述,我们到这里就把限流策略说完了。其实并不复杂。我们需要了解每个规则如何使用以及效果如何。