Sentinel熔断和限流

Sentinel熔断和限流

一、sentinel

官网:
https://github.com/alibaba/Sentinel
https://github.com/alibaba/Sentinel/wiki
下载:
https://github.com/alibaba/Sentinel/releases
文档:
https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_sentinel

服务使用中的各种问题:

  • 服务雪崩
  • 服务降级
  • 服务熔断
  • 服务限流

二、安装Sentinel控制台

2.1、sentinel组件由2部分组成

  • 后台
  • 前台8080

2、安装步骤
下载:https://github.com/alibaba/Sentinel/releases
下载到本地 sentinel-dashboard-1.7.0.jar

运行命令

java -jar sentinel-dashboard-1.7.0.jar
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

访问 sentinel 管理界面:
http://localhost:8080
登录账号密码均为sentinel

Sentinel 分为两个部分:

  • 核心库(Java客户端) 不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo /Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard) 基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

三、初始化演示工程

控制台显示效果:

四、流控规则


进一步解释说明:

  • 资源名:唯一名称,默认请求路径。
  • 针对来源:Sentine可以针对调用者进行限流,填写微服务名,默认default(不区分来源)。
  • 阈值类型 / 单机阈值
    • QPS (每秒钟的请求数量) :当调用该api的QPS达到阈值的时候,进行限流。
    • 线程数:当调用该api的线程数达到阈值的时候,进行限流。
  • 是否集群:不需要集群。
  • 流控模式
    • 直接:api达到限流条件时,直接限流。
    • 关联:当关联的资源达到阈值时,就限流自己。
    • 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流) 【api级别的针对来源】。
  • 流控效果
    • 快速失败:直接失败,抛异常。
    • Warm Up:根据 codeFactor(冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值。
    • 排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为 QPS,否则无效。

4.1、直接模式(默认)

配置及说明:

4.2、关联模式:


postman 模拟密集访问 testB:

4.3、链路模式:

只针对从指定链路访问到本资源的请求做统计,判断是否超过阈值,如果超过阈值对从该链路请求进行限流。
配置方法:
如果只希望统计从 /api/user/query 进入到 users 的请求,并进行限流操作,则可以这样配置:

// 在UserService中添加一个queryUsers方法,不用实现业务
public void queryUsers(){
    System.err.println("查询用户");
}

// 在上述Controller中,添加两个端点(请求方法),在这两个端点中分别调用UserService中的queryUsers方法
@GetMapping(value = "/save")
public String save() {
    userService.queryUsers();
    System.out.println("保存用户");
    return "订单保存成功" ;
}

@GetMapping(value = "/query")
public String query() {
    userService.queryUsers();
    System.out.println("查询用户");
    return "查询用户成功" ;
}

// 通过@SentinelResource标记UserService中的queryUsers方法为一个sentinel监控的资源(默认情况下,sentinel只监控controller方法)
@SentinelResource("users")
public void queryUsers(){
    System.err.println("查询用户");
}

// 更改application.yml文件中的sentinel配置
// 链路模式中,是对不同来源的两个链路做监控。但是sentinel默认会给进入spring mvc的所有请求设置同一个root资源,会导致链路模式失效。因此需要关闭这种资源整合。
spring:
  cloud:
    sentinel:
      web-context-unify: false # 关闭context整合

4.4、流控预热:

Warm Up (RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。详细文档可以参考流量控制-Warm Up 文档,具体的例子可以参见:
WarmUpFlowDemo。通常冷启动的过程系统允许通过的 QPS 曲线如下图所示:

Warmup 配置
默认 coldFactor 为 3,即请求QPS从 (threshold/3) 开始,经多少预热时长才逐渐升至设定的 QPS 阈值。

案例,阀值为 10+ 预热时长设置 5 秒。
系统初始化的阀值为 10/3 约等于 3,即阀值刚开始为 3。然后过了 5 秒后阀值才慢慢升高恢复到 10

应用场景:
如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。

4.5、排队等待:

匀速排队,让请求以均匀的速度通过,阀值类型必须设成 QPS,否则无效。
设置含义:/testA 每秒 1 次请求,超过的话就排队等待,等待的超时时间为20000毫秒。

匀速排队( Ruleconstant.CONTROL BEHAVIOR RATE_LIMITER) 方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。详细文档可以参考流量控制-匀速器模式,具体的例子可以参见 PaceFlowDemo

这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接本来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒真接拒绝多余的请求。

五、降级规则

5.1、RT(平均响应时间,秒级)

平均响应时间出阈值且在时间窗口内通过的请求 >=5,两个条件同时满足后触发降级窗口期过后关闭断路器。
RT 最大 4900 (更大的需要通过-Dcsp,sentinel.statistic.max.rt=XXXX才能生效)

5.2、异常比列(秒级)

QPS >=5 且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级。

5.3、异常数(分钟级)

异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级。

进一步说明:
Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。

复习Hystrix:

5.4、降级策略

平均响应时间(DEGRADE GRADE RT):当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule中的timewindow ,以s为单位)之内,对这个方法的调用都会自动地熔断(抛出DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作4900 ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=xxx来配置。

配置:

结论:

5.5、异常比例

异常比例(DEGRADE GRADE EXCEPTION RATIO ):当资源的每秒请求量>=5,并且每秒异常总数占通过量的比值超过阈值(DegradeRu1e中的count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRu1e 中的 timewindow ,以s为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是[0.0,1.0],代表 0%-100%。

配置:

jmeter:

结论:
按照上述配置,单独访问一次,必然来一次报错一次(int age = 10/0),调一次错一次;
异常比例(DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timewindow ,以s为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是[0.0, 1.0] ,代表0%-100%。
开启jmeter后,直接高并发发送请求,多次调用达到我们的配置条件了。
断路器开启(保险丝跳闸),微服务不可用了,不再报错 error 而是服务降级了。

5.6、异常数

异常数(DEGRADE GRADE EXCEPTION COUNT):当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若timewindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。

配置:

六、热点key限流

6.1、兜底方法

分为系统默认客户自定义,两种:
之前的case,限流出问题后,都是用sentinel系统默认的提示: Blocked by Sentinel (flow limiting)
我们能不能自定?类似hystrix,某个方法出问题了,就找对应的兜底降级方法?
结论:
HystrixCommand@SentinelResource

6.2、配置


参数例外项:

添加异常:
@SentinelResource
处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;
RuntimeException
int age = 10/0,这个是java运行时报出的运行时异常 RunTimeException@SentinelResource不管。
总结:
@SentinelResource 主管配置出错,运行出错该走异常走异常。

七、系统规则

各项配置参数说明:
系统保护规则是从应用级别的入口流量进行控制,从单台机器的load、CPU 使用率、平均RT、入口QPS和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN) ,比如Web服务或Dubbo 服务端接收的请求,都属于入口流量。

系统规则支持以下的模式:

  • Load自适应(仅对Linux/Unix-like机器生效):系统的 load 作为启发指标,进行自适应系统保护。当系统 load 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR阶段) 。系统容量由系统的 maxQps * minRt估算得出。设定参考值一般是 CPU cores * 2.5
  • CPU usage (1.5.0+版本):当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-1.0),比较灵敏。
  • 平均RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

八、@SentinelResorce

8.1、按资源名称限流 + 后续处理

配置步骤:

8.2、按Url地址限流 + 后续处理

配置:

上面兜底方法面临的问题:

  • 系统默认的,没有体现我们自己的业务要求。
  • 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观。
  • 每个业务方法都添加一个兜底的,那代码膨胀加剧。
  • 全局统一的处理方法没有体现。

更多注解属性说明:

  • value:作用指定资源名称,必填。
  • entryType:entry类型,标记流量的方向,指明是出口流量,还是入口流量;取值 IN/OUT,默认是 OUT。非必填。
  • blockHandler:处理 BlockException 的函数名称,函数要求为必须是 public 返回类型与原方法一致参数类型需要和原方法相匹配,并在最后加上BlockException类型的参数默认需和原方法在同一个类中,如果希望使用其他类的函数,可配置blockHandlerClass,并指定blockHandlerClass里面的方法。
  • blockHandlerClass:存放blockHandler的类。对应的处理函数必须static修饰,否则无法解析。函数要求为:必须是public 返回类型与原方法一致参数类型需要和原方法相匹配,并在最后加上BlockException类型的参数。
  • fallback:用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了execptionsToIgnore 里面排除掉的异常类型)进行处理,函数要求为:返回类型与原方法一致 参数类型需要和原方法相匹配,Sentinel 1.6版本之后,也可在方法最后加上Throwable类型的参数,默认需和原方法在同一个类中,若希望使用其他类的函数,可配置fallbackClass,并指定fallbackClass里面的方法。
  • fallbackClass:存放fallback的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同fallback。
  • defaultFallback:用于通用的 fallback 逻辑。默认fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了fallbackdefaultFallback,以fallback为准。函数要求:返回类型与原方法一致 方法参数列表为空,或者有一个Throwable类型的参数 默认需要和原方法在同一个类中,若希望使用其他类的函数,可配置fallbackclass,并指定fallbackClass里面的方法。
  • exceptionsToIgnore:指定排除掉哪些异常。排除的异常不会计入异常统计,也不会进入fallback逻辑,而是原样抛出。
  • exceptionsToTrace:需要trace的异常。

九、服务熔断功能

熔断框架比较:

参考:
Sentinel简单使用

评论

暂无

添加新评论