• 「SpringCloud Alibaba」Sentinel实现熔断与限流


    SpringCloud Alibaba—Sentinel实现熔断与限流

    笔记整理自【尚硅谷】周阳SpringCloud框架开发教程

    sentinel

    image-20220801123922304

    1. Sentinel简介

    image-20220911180022296

    image-20220911182331788

    一句话,Sentinel就是升级的Hystrix。

    Ⅰ. Sentinel是什么

    官网

    随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应过载保护、热点流量防护等多个维度保护服务的稳定性。

    Sentinel 具有以下特征:

    • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
    • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
    • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
    • 完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

    Ⅱ. Sentinel能做什么

    Sentinel 的主要特性

    image-20220911180854713

    Sentinel 的开源生态

    84338449-a9497e00-abce-11ea-8c6a-473fe477b9a1

    Ⅲ. Sentinel怎么使用

    官网使用教程

    服务使用中的各种问题

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

    image-20220912164036036

    2. 安装Sentinel控制台

    Sentinel 分为两个部分:

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

    安装步骤

    • 下载到本地:sentinel-dashboard-1.8.5.jar

    • 运行命令

      java -jar sentinel-dashboard-1.8.5.jar
      

      image-20220911190713671

      前提需要java8环境,且8080端口不能被占用。

    • 访问 http://localhost:8080,账号密码均为sentinel

      image-20220911190843148

      image-20220911190858598

    3. 初始化演示工程

    • 启动Nacos8848成功

      http://localhost:8848/nacos/#/login

    • 建Module

      cloudalibaba-sentinel-service8401

    • 改POM

      下面这3个依赖就是Nacos + Sentinel的标配

      
      <dependency>
          <groupId>com.alibaba.cloudgroupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
      dependency>
      
      <dependency>
          <groupId>com.alibaba.cspgroupId>
          <artifactId>sentinel-datasource-nacosartifactId>
      dependency>
      
      <dependency>
          <groupId>com.alibaba.cloudgroupId>
          <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
      dependency>
      

      image-20220911195253560

      OpenFeign后面会用到。

    • 写YML

      image-20220911200017129

    • 主启动

      image-20220911195458276

    • 业务类

      FlowLimitController

      image-20220911195537131

    • 测试

      ➢ 启动Sentinel8080

      ➢ 启动微服务8401

      image-20220911200533305

      ➢ 查看sentienl控制台

      空空如也,啥都没有

      image-20220911200304391

      ➢ Sentinel采用的懒加载说明

      执行一次访问即可

      http://localhost:8401/testA

      http://localhost:8401/testB

      ➢ 效果

      image-20220911200508517

      Sentinel8080正在监控微服务8401。

    4. 流控规则

    Ⅰ. 基本介绍

    流量限制控制规则,分为:流控模式流控效果

    image-20220911200931064

    解释说明

    image-20220917120421819

    Ⅱ. 流控模式

    1️⃣ 直接(默认)

    api达到限流条件时,直接限流

    • 直接 => 快速失败(系统默认)

    • 可以直接点击簇点链路添加流控

      image-20220911202031188

    • 配置及说明

      阈值类型为QPS

      表示1秒钟内查询1次就是OK,若超过次数1,就直接 => 快速失败,报默认错误

      image-20220911201722056

      image-20220911202155521

    • 测试

      ➢ 快速点击访问:http://localhost:8401/testA

      ➢ 结果

      Blocked by Sentinel (flow limiting)

      image-20220911202238429

      ➢ 思考

      直接调用默认报错信息,技术方面OK,但,是否应该有我们自己的后续处理?

      比如:类似有个fallback的兜底方法?

    扩展:阈值类型为线程数

    image-20220911203721192

    当调用该api的线程数达到阈值的时候,进行限流。

    与QPS直接快速失败不同的是,QPS情况下限制的是流量,比如银行的人流量只能是1人/s,也就是说每秒只能一个人进入银行办理业务;

    而线程数就好比银行只有一个窗口开放,一群人都可以进入银行,但是每次只能处理一个人的业务

    • 演示效果

      修改一下8401的业务类:

      image-20220911203530361

    • 测试

      开两个页面访问:http://localhost:8401/testA

      同时抢占,一个直接快速失败,另一个在处理请求

      image-20220911204055752

    2️⃣ 关联

    当关联的资源达到阈值时,就限流自己

    • 当与A关联的资源B达到阀值后,就限流A自己
    • B惹事,A挂了
    • 配置A

      设置效果

      当关联资源/testB的qps阀值超过1时,就限流/testA的Rest访问地址,当关联资源到阈值后限制配置好的资源名。

      Ex:假如支付接口/testB即将瘫痪,那么限制下单接口/testA。

      image-20220911211056010

    • postman模拟并发密集访问testB

      image-20220911211657702

      ➢ 访问testB成功

      image-20220911211714090

      ➢ postman里新建多线程集合组

      image-20220911211731538

      ➢ 将访问地址添加进新新线程组

      image-20220911211738375

      ➢ Run

      image-20220911211744379

      大批量线程高并发访问B,导致A失效了。

      image-20220911220807109

    3️⃣ 链路

    多个请求调用了同一个微服务。

    只针对从指定链路访问到本资源的请求做统计,判断是否超过阈值。

    需要测试链路的话,Spring Cloud Alibaba 版本需要2.1.1.RELEASE以上,在父工程的pom中修改,不要直接在子odule的pom中修改,版本有对应关系,不然报错。

    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-alibaba-dependenciesartifactId>
        <version>2.1.1.RELEASEversion>
        <type>pomtype>
        <scope>importscope>
    dependency>
    
    • Sentinel从1.6.3版本开始,Sentinel Web Filter 默认收敛所有的URL入口的Context,因此链路限流不生效

    • 1.7.0版本开始,官方在CommomFilter中引入了WEB_CONTEXT_UNIFY这个init parameter,用于控制是否收敛context,将其配置为false即可根据不同的URL进行链路限流

    • Spring Cloud Alibaba 在2.1.1.RELEASE版本后,可以通过配置spring.cloud.sentinel.web-context-unify=false关闭

    • 参考

      image-20220912112310710

    • 测试

      启动8401,给/testA设置链路 + 快速失败流控规则,入口资源填写/testA的入口资源地址sentinel_web_servlet_context

      image.png

      然后再发送请求至 http://localhost:8401/testA 时,如果1秒内请求次数超过1次,就会自动触发限流。
      此外,通过其他微服务模块请求/testA时,如果1秒内请求次数超过1次,同样会触发限流。

      image-20220912112808877

      但是不会对/testB限制。

    • 解释

      实际上,链路的控制指的就是对一条链路的访问进行控制。

      比方说,我有一个二叉树:

      image-20220912113150350

      a => b => d,a => b => e,a => c => f,a => c => g 均可视作链路。

      假设我以a为入口资源,d为终点资源,对这条链路进行限制的话,则资源a,b,d均会被限制访问。

    Ⅲ. 流控效果

    1️⃣ 直接 => 快速失败(默认的流控处理)

    直接失败,抛出异常

    Blocked by Sentinel (flow limiting)

    • 源码

      com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController

    2️⃣ Warm Up 预热

    根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值。

    • 公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值。

    • 官网

      image-20220912105024044

      默认coldFactor为3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。

      限流 冷启动

    • 源码

      image-20220912105125511

    • Warm Up配置

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

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

      image-20220912105302802

    • 测试

      多次点击:http://localhost:8401/testB

      刚开始扛不住,后续慢慢的能抗住了:

      B

    • 应用场景

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

    3️⃣ 排队等待

    匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效。

    • 官网

      image-20220912114921704

    • 设置含义:/testA每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒。

      image-20220912115418046

      匀速排队,阈值必须设置为QPS。

    • 源码

      com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController

    • 测试

      @GetMapping("/testB")
      public String testB() {
          log.info(Thread.currentThread().getName() + "\t" + "...testB");
          return "-----testB";
      }
      

      image-20220912114942209

      可以看到刚好满足1s一个请求,说明请求的执行进行了排队。

      image-20220912120005479

    5. 降级规则

    Ⅰ. 基本介绍

    官网

    Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。

    当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。

    老版本的Sentinel的断路器是没有半开状态的,半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用。具体可以参考Hystrix(在Hystrix中 快照时间窗口是值 阈值检测时间 ,而休眠时间窗口是指 断路器从开启到半开状态间隔的时间)。

    新版本的Sentinel加入了半开状态!

    Sentinel在1.8.0版本对熔断降级做了大的调整,可以定义任意时长的熔断时间,引入了半开启恢复支持。下面梳理下相关特性。

    熔断状态

    熔断状态有三种状态,非别为OPEN、HALF_OPEN、CLOSED

    状态说明
    OPEN表示熔断开启,拒绝所有请求
    HALF_OPEN探测恢复状态,如果接下来的一个请求顺利通过则表示结束熔断,否则继续熔断
    CLOSE表示熔断关闭,请求顺利通过

    熔断降级规则说明

    熔断降级规则(DegradeRule)包含下面几个重要的属性:

    Field说明默认值
    resource资源名,即规则的作用对象
    grade熔断策略,支持慢调用比例/异常比例/异常数策略慢调用比例
    count慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值
    timeWindow熔断时长,单位为 s
    minRequestAmount熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入)5
    statIntervalMs统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入)1000 ms
    slowRatioThreshold慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

    Ⅱ. 降级策略实战

    1️⃣ 慢调用比例,RT(平均响应时间,秒级)

    老版本:

    image.png

    image-20220912123857446

    新版本:

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

      image-20220912133936008

      image-20220912162035551

    测试

    • 代码

      image-20220912135045974

    • 配置

      熔断规则

      在1000ms的统计时间内,总请求数(超过5次)中有80%的请求最大RT超过了200ms,那么触发熔断机制,熔断2s。

      image.png

    • jmeter压测

      image-20220912142249644

    • 结论

      永远一秒钟打进来10个线程(大于5个了)调用testD,我们希望200毫秒处理完本次任务,如果超过200毫秒还没处理完,在未来s秒钟的时间内,断路器打开(保险丝跳闸)微服务不可用,保险丝跳闸断电了。

      testD被熔断了:

      image-20220912141953180

      从实时监控也可以看到,在09的时候开始熔断:

      image.png

      后续停止jmeter,没有这么大的访问量了,断路器半开到关闭(保险丝恢复),微服务恢复OK。

    2️⃣ 异常比例(秒级)

    老版本:

    image-20220912131709616

    image-20220912132144398

    新版本:

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

      image-20220912134015136

      image-20220912162128078

    测试

    • 代码

      image-20220912151956161

    • 配置

      熔断规则

      image.png

    • jmeter压测

    • 结论

      单独访问一次,必然来一次报错一次 (int age = 10/0) ,调一次错一次;

      image-20220912151207730

      开启jmeter后,直接高并发发送请求,多次调用达到我们的配置条件了,断路器开启(保险丝跳闸),微服务不可用了,不再报错error而是服务降级了。

      image-20220912151236430

      停掉jemeter后过2s,报/zero错误。

    3️⃣ 异常数(分钟级)

    老版本:

    image-20220912131944957

    image-20220912132204871

    新版本:

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

      image-20220912134041720

      image-20220912162157280

    测试

    • 代码

      image-20220912152027662

    • 配置

      熔断规则

      image.png

    • 手动测试

    • 结论

      image-20220912154512510

      这里测试出现了Bug,虽然熔断了 但熔断时长不是我配置的5s,熔断了很久大概1分钟,统计时长也不是1s,因为我手动很慢的测试,同时没达到最小请求数,只达到3次异常就直接熔断了。但老师演示的老版本就可以依据配置进行熔断,可能是不会使用新版本。

      我发现我根本改不了配置的统计时长,如果按照老版本的是按照分钟统计异常数,设置时间窗口 >= 60s,那新版本理应设置统计时长 >= 60000ms,但我修改统计时长后再编辑 还是默认的1000,虽然新版本没说异常数是分钟级的,但是修改不了统计时长就很迷惑。上面修改慢调用比例的比例阈值也没效果,但异常比例的比例阈值可以修改。

      搞不懂。

    6. 热点key限流

    Ⅰ. 基本介绍

    官网

    何为热点

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

    • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
    • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

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

    image.png

    Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。

    image-20220912173435999

    承上启下复习

    兜底方法

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

    结论

    • @HystrixCommand@SentinelResource

    Ⅱ. 代码演示

    • 新增

      @SentinelResource

      image-20220912180131449

      如果你违背了@SentinelResource对控制台配置的规则,就会执行兜底的方法。

    • 配置

      image-20220912181024232

      这里资源名是根据 @SentinelResource 注解的 value 属性值配置的。

      限流模式只支持QPS模式,固定写死了。(这才叫热点)

      @SentinelResource注解的方法参数索引,0代表第一个参数,1代表第二个参数,以此类推。

      单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。

      上面的抓图就是第一个参数有值的话,1秒的QPS为1,超过就限流,限流后调用dealHandler_testHotKey支持方法。

      image-20220912181135419

    • 测试

      ➢ 使用兜底方法

      http://localhost:8401/testHotKey?p1=a

      image-20220912181810675

      image-20220912182314903

      ➢ 不使用兜底方法

      http://localhost:8401/testHotKey?p1=a

      @SentinelResource注解中的blockHandler属性去掉:

      image-20220912182029354

      image-20220912182120182

    • 小总结

      ➢ ❌ error http://localhost:8401/testHotKey?p1=abc

      ➢ ❌ error http://localhost:8401/testHotKey?p1=abc&p2=33

      ➢ ✔️ right http://localhost:8401/testHotKey?p2=abc

      只要带上p1参数且违背了规则 就会降级限流。

    Ⅲ. 参数例外项

    上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流。

    • 特例情况

      ➢ 普通:超过1秒钟一个后,达到阈值1后马上被限流

      我们期望p1参数当它是某个特殊值时,它的限流值和平时不一样

      特例:假如当p1的值等于5时,它的阈值可以达到200

    • 配置

      参数类型只支持8种基本类型和String类型。

      image-20220912204120465

      添加成功

      image-20220912204513073

    • 测试

      ➢ ✔️ http://localhost:8401/testHotKey?p1=5

      image-20220912204531126

      ➢ ❌ http://localhost:8401/testHotKey?p1=3

      image-20220912204541459

      当p1等于5的时候,阈值变为200,当p1不等于5的时候,阈值就是平常的1。

    7. 系统规则

    官网

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

    系统保护规则是从应用级别的入口流量进行控制,从单台机器的 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 达到阈值即触发系统保护。

    image-20220912205410643

    配置全局QPS

    image-20220912205701589

    • 不管是/testA还是/testB,只要QPS > 1 整个系统就不能用。
    • 这个粒度太粗,就相当于一个窗口人很多,整个银行就不接待人了,不太建议使用。

    8. @SentinelResource

    Ⅰ. 按资源名称限流 + 后续处理

    • 启动Nacos成功

    • 启动Sentinel成功

    • 改Module

      修改cloudalibaba-sentinel-service8401

    • 改POM

      
      
      	com.atguigu.springcloud
      	cloud-api-commons
      	${project.version}
      
      

      image-20220912210457808

    • 业务类

      RateLimitController

      image-20220912210831444

    • 主启动

      image-20220912210944949

    • 配置流控规则

      ➢ 配置步骤

      image-20220912211558513

      ➢ 图形配置和代码关系

      image-20220912212220949

      表示1秒钟内查询次数大于1,就跑到我们自定义的处理,限流。

    • 测试

      ➢ 1秒钟点击1下,OK

      image-20220912213515311

      ➢ 超过上述,疯狂点击,返回了自己定义的限流处理信息,限流发生

      image-20220912213506028

    • 额外问题

      此时关闭问服务8401看看

      Sentinel控制台,流控规则消失了??

      临时/持久?

    Ⅱ. 按照Url地址限流 + 后续处理

    通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息。

    • 业务类

      RateLimitController

      不配置blockHandler属性,没有兜底方法。

      image-20220912214126823

    • Sentinel控制台配置

      这里是根据URL进行限流。

      image-20220912214451953

    • 测试

      ➢ 正常点击:http://localhost:8401/rateLimit/byUrl

      image-20220912214523432

      ➢ 疯狂点击:http://localhost:8401/rateLimit/byUrl

      结果

      image-20220912214706293

      会返回Sentinel自带的限流处理结果。

    Ⅲ. 上面兜底方案面临的问题

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

    又回到了当时Hystrix的问题。

    Ⅳ. 客户自定义限流处理逻辑

    解决上述问题,创建CustomerBlockHandler类用于自定义限流处理逻辑。

    • 自定义限流处理类

      CustomerBlockHandler

      image-20220912220105036

      image-20220912220412756

    • 业务类

      RateLimitController

      image-20220912220635284

    • Sentinel控制台配置

      image-20220912220808302

    • 测试

      正常访问:http://localhost:8401/rateLimit/customerBlockHandler

      image-20220912220750454

      狂点:http://localhost:8401/rateLimit/customerBlockHandler

      兜底的方法是全局的2号方法。

      image-20220912220913459

      完成了业务与代码的解耦,代码膨胀。

    • 进一步说明

      image-20220912221042824

    Ⅴ. 更多注解属性说明

    注解支持文档

    image-20220913123427919

    image-20220913123439886

    多说一嘴

    image-20220913123646856

    所有的代码都要用try-catch-finally方式进行处理。

    Sentinel主要有三个核心Api

    • SphU定义资源
    • Tracer定义统计
    • ContextUtil定义了上下文

    9. 服务熔断功能

    Sentinel 整合 Ribbon + OpenFeign + fallback

    Ⅰ. Ribbon系列

    image-20220913125019130

    1️⃣ 提供者9003/9004
    • 建Module

      新建cloudalibaba-provider-payment9003/9004两个一样的做法

    • 改POM

      <dependencies>
          
          <dependency>
              <groupId>com.alibaba.cloudgroupId>
              <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
          dependency>
          <dependency>
              <groupId>com.atguigu.springcloudgroupId>
              <artifactId>cloud-api-commonsartifactId>
              <version>${project.version}version>
          dependency>
          
          <dependency>
              <groupId>org.springframework.bootgroupId>
              <artifactId>spring-boot-starter-webartifactId>
          dependency>
          <dependency>
              <groupId>org.springframework.bootgroupId>
              <artifactId>spring-boot-starter-actuatorartifactId>
          dependency>
          
          <dependency>
              <groupId>org.springframework.bootgroupId>
              <artifactId>spring-boot-devtoolsartifactId>
              <scope>runtimescope>
              <optional>trueoptional>
          dependency>
          <dependency>
              <groupId>org.projectlombokgroupId>
              <artifactId>lombokartifactId>
              <optional>trueoptional>
          dependency>
          <dependency>
              <groupId>org.springframework.bootgroupId>
              <artifactId>spring-boot-starter-testartifactId>
              <scope>testscope>
          dependency>
      dependencies>
      
    • 写YML

      image-20220913124351102

    • 主启动

      image-20220913124410952

    • 业务类

      模拟数据库的DAO层。

      image-20220913124705642

    • 测试

      ➢ http://localhost:9003/paymentSQL/1

      image-20220913125337379

      ➢ http://localhost:9004/paymentSQL/1

      image-20220913140225193

    2️⃣ 消费者84
    • 建Module

      cloudalibaba-consumer-nacos-order84

    • 改POM

      image-20220913140355207

    • 写YML

      image-20220913140453517

    • 主启动

      image-20220913140521958

    • 业务类

      config.ApplicationContextConfig

      image-20220913140641134

      controller.CircleBreakerController

      目的:fallback管运行异常,blockHandler管配置违规。

      测试:http://localhost:84/consumer/fallback/1

      1️⃣ 没有任何配置

      image-20220913143230715

      结果

      给客户error页面,不友好

      ➢ http://localhost:84/consumer/fallback/4

      image-20220913143427826

      ➢ http://localhost:84/consumer/fallback/5

      image-20220913143501344

      2️⃣ 只配置fallback

      image-20220913143641971

      说明

      image-20220913142023976

      本例Sentinel无配置。

      结果

      执行了兜底的handlerFallback方法。

      image-20220913142044830

      3️⃣ 只配置blockHandler

      image-20220913142704661

      说明

      image-20220913142724370

      本例sentinel需配置:

      异常超过2次后,断路器打开,断电跳闸,系统被保护。

      image-20220913144141110

      结果

      服务被降级。

      image-20220913145028460

      4️⃣ fallback和blockHandler都配置

      image-20220913144611326

      说明

      image-20220913144649956

      本例sentinel需配置:

      image-20220913144706696

      结果

      没超过QPS,也就是没违反Sentinel中配置的规则,有运行异常则交给fallback处理:

      image-20220913145233226

      违反了Sentinel中配置的规则,即使有运行异常,降级也交给blockHandler处理:

      若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。

      5️⃣ 忽略属性…

      image-20220913145803349

      说明

      image-20220913145819868

      本例sentinel无配置。

      结果

      程序异常打到前台了,对用户不友好。

      image-20220913150012002

      其他页面没有影响:

      image-20220913150211778

      当然,触发流控之后,仍然通过blockHandler指定的方法进行熔断兜底。

    • 总结

      fallback + blockHandler两个一起配置,降级和限流的保护措施会更加完善。

    Ⅱ. Feign系列

    • 改Module

      修改cloudalibaba-consumer-nacos-order84模块

      84消费者调用提供者9003

      Feign组件一般是消费侧

    • 改POM

      添加OpenFeign

      
      <dependency>
      	<groupId>org.springframework.cloudgroupId>
      	<artifactId>spring-cloud-starter-openfeignartifactId>
      dependency>
      
    • 写YML

      激活Sentinel对Feign的支持

      image-20220913154938889

    • 主启动

      @EnableFeignClients

      image-20220913155108003

    • 业务类

      ➢ 带@FeignClient注解的业务接口

      service.PaymentService

      image-20220913155225178

      ➢ 实现接口

      fallback = PaymentFallbackService.class => service.PaymentFallbackService

      image-20220913155754520

      controller.CircleBreakerController

      image-20220913155456977

    • 测试

      http://localhost:84/consumer/openfeign/1

      image-20220913161614236

      测试84调用9003,此时故意关闭9003微服务提供者,看84消费侧自动降级,不会被耗死。

      image-20220913161709399

    Ⅲ. 熔断框架比较

    image.png

    10. 规则持久化

    一旦我们重启应用,Sentinel规则将消失,生产环境需要将配置规则进行持久化。

    将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,Sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上Sentinel上的流控规则持续有效。

    步骤

    • 改Module

      修改cloudalibaba-sentinel-service8401

    • 改POM

      之前已引入

      
      <dependency>
          <groupId>com.alibaba.cspgroupId>
          <artifactId>sentinel-datasource-nacosartifactId>
      dependency>
      
    • 写YML

      添加Nacos数据源配置

      image-20220913162518339

    • 添加Nacos业务规则配置

      image-20220913165009920

      [
          {
              "resource": "/rateLimit/byUrl",
              "limitApp": "default",
              "grade": 1,
              "count": 1,
              "strategy": 0,
              "controlBehavior": 0,
              "clusterMode": false
          }
      ]
      
      resource:资源名称;
      limitApp:来源应用;
      grade:阈值类型,0表示线程数,1表示QPS;
      count:单机阈值;
      strategy:流控模式,0表示直接,1表示关联,2表示链路;
      controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
      clusterMode:是否集群。
      
    • 启动8401后刷新sentinel发现业务规则有了

      image-20220913171126751

    • 快速访问测试接口:http://localhost:8401/rateLimit/byUrl

      配置生效

      image-20220913170815600

    • 停止8401再看Sentinel

      停机后发现流控规则没有了

      image-20220913171218441

    • 重新启动8401再看Sentinel

      乍一看还是没有,稍等一会儿;

      多次调用:http://localhost:8401/rateLimit/byUrl

      配置重新出现了,持久化验证通过。

  • 相关阅读:
    RabbitMQ之ttl(过期消息)解读
    XTU-OJ 1255-勾股数
    PHP:纤程
    KWin、libdrm、DRM从上到下全过程 —— drmModeAddFBxxx(17)
    PyTorch学习笔记之基础函数篇(八)
    ES 架构及基础 - 1
    Kubeadm安装k8s高可用集群实战
    EN 13241工业、商业、车库门和大门—CE认证
    【CSS】BFC 块级格式化上下文
    简单钟表动画
  • 原文地址:https://blog.csdn.net/weixin_53407527/article/details/126903443