当前位置: 首页 > news >正文

「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的标配

    <!-- SpringCloud ailibaba nacos -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!-- SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到 -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    <!-- SpringCloud ailibaba sentinel -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </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.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.1.1.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</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

    <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
    <dependency>
    	<groupId>com.atguigu.springcloud</groupId>
    	<artifactId>cloud-api-commons</artifactId>
    	<version>${project.version}</version>
    </dependency>
    

    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>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </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

    <!-- SpringCloud openfeign -->
    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-starter-openfeign</artifactId>
    </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

    之前已引入

    <!-- SpringCloud ailibaba sentinel-datasource-nacos 做持久化-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </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

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

相关文章:

  • 赶紧进来看看---详细介绍五种常用字符串库函数 以及对库函数的模拟实现
  • 浅谈 python在密码学的应用
  • lammps数据后处理:python绘制应力应变曲线 附程序代码
  • 机器学习模型2——决策树
  • Java.lang.Character类中codePointAt(CharSequence seq, int index)方法具有什么功能呢?
  • docker-compose 安装Harbor
  • 微服务项目:尚融宝(52)(核心业务流程:充值服务(3))
  • python的小作业
  • 2022届计算机毕业论文(设计)学生选题参考合集推荐收藏
  • AI艺术的背后:详解文本生成图像模型【基于GAN】
  • NR 物理层编码 - slide4 循环码Cyclic Code
  • 内网渗透-内网信息收集
  • 新学期、新目标、迎接新的自己
  • 2022年重庆自考如何报名,有哪些条件和要求?
  • 70 QDateTime时间戳转换有误
  • es6
  • ESLint简单操作
  • input实现文字超出省略号功能
  • JavaScript类型识别
  • Js基础——数据类型之Null和Undefined
  • miaov-React 最佳入门
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • Vultr 教程目录
  • 理解在java “”i=i++;”所发生的事情
  • 一个项目push到多个远程Git仓库
  • 最近的计划
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (33)STM32——485实验笔记
  • (JS基础)String 类型
  • (七)Knockout 创建自定义绑定
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (一)Thymeleaf用法——Thymeleaf简介
  • (转)负载均衡,回话保持,cookie
  • (转)关于pipe()的详细解析
  • (转)母版页和相对路径
  • (转)四层和七层负载均衡的区别
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .NET 5种线程安全集合
  • .net 反编译_.net反编译的相关问题
  • .NET 命令行参数包含应用程序路径吗?
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .net6Api后台+uniapp导出Excel
  • .Net面试题4
  • .NET中使用Redis (二)
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [51nod1610]路径计数
  • [AIGC] Redis基础命令集详细介绍
  • [BZOJ1053][HAOI2007]反素数ant
  • [BZOJ4554][TJOI2016HEOI2016]游戏(匈牙利)
  • [C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]