【SpringCloud Alibaba】Sentinel配置、流量控制、熔断降级、限流、规则持久化

🔰 学习视频 🔰

尚硅谷SpringCloud框架开发教程(SpringCloudAlibaba微服务分布式架构丨Spring Cloud)

集数:111—137


🔰 项目地址 🔰

https://gitee.com/zqcliudaliuda/cloud2021


一、简介

github介绍Spring官网介绍

Sentinel:分布式系统的流量防卫兵

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

Sentinel 具有以下特征:

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

Sentinel 的主要特性:
在这里插入图片描述
Sentinel 的开源生态:
在这里插入图片描述

Sentinel 分为两个部分:

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

二、下载安装

🔶 下载https://github.com/alibaba/Sentinel/releases

选择1.7.0版本。
在这里插入图片描述

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

🔶 运行

保证java8安装成功,且8080端口不被占用。

双击直接运行:sentinel-dashboard-1.7.0.jar

运行后访问:http://localhost:8080/

账号密码均为sentinel

在这里插入图片描述

三、初始化演示工程

3.1 新建项目

🔶 新建maven工程

新建maven工程:cloudalibaba-sentinel-service8401

🔶 POM

<dependencies>
    <!-- SpringCloud alibaba sentinel-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!-- SpringCloud alibaba nacos-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!-- SpringCloud alibaba sentinel-datasource-nacos 持久化用的-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <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>

    <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>

🔶 application.yml

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080 # 配置sentinel dashboard地址
        port: 8719 # 默认8179端口,如果被占用会自动从8719依次+1扫描,直到找到未被占用的端口
        
management:
  endpoints:
    web:
      exposure:
        include: '*'

🔶 主启动类

@SpringBootApplication
@EnableDiscoveryClient
@RefreshScope
public class MainApp8401 {
    public static void main(String[] args) {
        SpringApplication.run(MainApp8401.class, args);
    }
}

🔶 业务类

@RestController
public class FlowLimitController {
    @GetMapping("/testA")
    public String testA() {
        return "------testA";
    }
    @GetMapping("/testB")
    public String testB() {
        return "------testB";
    }
}

3.2 测试

启动nacos微服务8848(在windows上启动即可),双击运行即可。
启动sentinel微服务8080,双击运行或java -jar sentinel-dashboard-1.7.0.jar
启动微服务8401。

此时访问:http://localhost:8080/
在这里插入图片描述
空空如也,因为sentinel使用的懒加载模式,必须先访问一次才行。

访问:http://localhost:8401/testA
访问:http://localhost:8401/testB

在这里插入图片描述

四、流量控制

4.1 基本介绍

流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
在这里插入图片描述

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

4.2 流控模式

4.2.1 默认直接

为资源添加流控
在这里插入图片描述
编辑流控规则,1秒1次。
在这里插入图片描述
访问:http://localhost:8401/testA

如果访问速度没有超过1次/s,正常访问;如果访问速度超过1次/s,快速失败,报默认错误。

Blocked by Sentinel (flow limiting)

后面,将对默认报错进行修改,设置fallback。

4.2.2 关联

当关联的资源达到阙值时,就限流自己;当与A关联的资源B达到阙值后,就限流A自己;B惹事,A挂了。比如,如果支付接口达到阈值就限流订单接口。
在这里插入图片描述
当关联资源/testB的qps阀值超过1时,就限流/testA的Rest访问地址,当关联资源到阈值后限制配置好的资源名。

使用POSTMAN模拟并发访问/testB

创建一个集合,添加一个请求到集合。
在这里插入图片描述
设置20个线程,每0.3秒就有一个线程发过去。
在这里插入图片描述
此时访问:http://localhost:8401/testA,A会被限制。

4.3 流控效果

4.3.1 快速失败

直接拒绝(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)方式是默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。

4.3.2 Warm up

Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
在这里插入图片描述
案例:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。

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

默认coldFactor为3,即请求QPS从(threshold/ 3)开始,经多少预热时长才逐渐升至设定的QPS阈值。
在这里插入图片描述

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

快速访问:http://localhost:8401/testB

一开始会出现限流,慢慢的话就不会出现限流了。

4.3.3 排队等待

匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。

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

注意:匀速排队模式暂时不支持 QPS > 1000 的场景。

在这里插入图片描述
修改业务类

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

设置postman
在这里插入图片描述
启动8401、启动postman测试:

idea控制台输出
在这里插入图片描述
每一个响应都大致间隔两秒,每一个请求都有响应,只不过要排队等待。

五、熔断降级

5.1 概述

除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。
在这里插入图片描述

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

5.2 降级策略

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

5.2.1 平均响应时间RT

🔶 说明

平均响应时间(秒级)超出阈值在时间窗口内通过的请求>=5, 两个条件同时满足后触发降级窗口期过后关闭断路器

RT最大4900 (更大的需要通过Dcsp.sentinel.statistic.max.rt=XXXX才能生效)。

在这里插入图片描述
🔶 测试

在服务类中添加:

@GetMapping("/testD")
public String testD() {
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "------testD";
}

配置降级规则
在这里插入图片描述
启动jmeter,新建线程组,线程数10,永久循环。
在这里插入图片描述
设置ip、端口号和访问路径,开始运行。
在这里插入图片描述

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

5.2.2 异常比例

🔶 说明

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

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

🔶 测试

新增降级规则
在这里插入图片描述
修改业务类

@GetMapping("/testD")
public String testD() {
//        try {
//            TimeUnit.SECONDS.sleep(1);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        System.out.println("testD");
    int a = 10/0;
    System.out.println("异常比例 testD");
    return "------testD";
}

启动jmeter,新建线程组,线程数10,永久循环。
在这里插入图片描述
设置ip、端口号和访问路径,开始运行。
在这里插入图片描述
测试时,如果配置成功的话,访问http://localhost:8401/testD会出现:

Blocked by Sentinel (flow limiting)

按照上述配置,单独访问一次,必然来一次报错一次(int age = 10/0), 调一次错一次;
在这里插入图片描述
开启jmeter后,直接高并发发送请求,多次调用达到我们的配置条件了。断路器开启(保险丝跳闸),微服务不可用了,不再报错error而是服务降级了。

5.2.3 异常数

🔶 说明

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

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

🔶 测试

编辑降级规则
在这里插入图片描述
访问5次:http://localhost:8401/testD

前五次时报错,第六次开始降级熔断。

六、热点参数限流

6.1 概述

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

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
    热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

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

6.2 设置测试

业务类FlowLimitController中增加:

@GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
    public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                             @RequestParam(value = "p2", required = false) String p2) {
        return "----------testHotKey";
    }

    public String deal_testHotKey(String p1, String p2, BlockException exception) {
        return "----------deal testHotKey";  // sentinel系统默认提升:Blocked by Sentinel (flow limiting)
    }

访问:http://localhost:8401/testHotKeyhttp://localhost:8401/testHotKey?p1=1&p2=2,成功:

----------testHotKey

启动8401微服务,新增热点配置规则:索引为0是针对第一个参数,该索引的访问不能超过1次/s。

在这里插入图片描述
快速访问:http://localhost:8401/testHotKey?p1=1&p2=2

第一次成功,一秒钟超过2次的话,会调用我们自定义的兜底方法deal_testHotKey。因为设置了@SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey"),选择了兜底方法。

如果不配置兜底方法的话,将出现Error Page,不友好的用户提示。

访问次数限制:http://localhost:8401/testHotKey?p1=1&p2=2
访问次数限制:http://localhost:8401/testHotKey?p1=1
访问次数不限制:http://localhost:8401/testHotKey?p2=2

6.3 参数例外项测试

普通设置,超过秒钟一个后,达到阙值1后马上被限流;但,我们期望p1参数当它是某个特殊值的时候,它的限流值和平时不一样,假如当p1的值等于5时,它的阙值可以达到200。
在这里插入图片描述
当参数值为5的时候,限流阈值变为200,其他值的时候为1。

访问:http://localhost:8401/testHotKey?p1=1,被限制
访问:http://localhost:8401/testHotKey?p1=5,QPS达到200,一直刷新也观察不到限制。

🔶 注意:

@SentinelResource:处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;
RuntimeExceptionint age = 10/0,这个是java运行时报出的运行时异常RunTimeException。

@SentinelResource主管配置出错,运行出错该走异常走异常

七、系统自适应限流

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

  • 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 达到阈值即触发系统保护。

八、SentinelResource

8.1 正常情况

修改8401微服务

🔶 新增POM依赖,引入之前建立的module:cloud-api-commons

<!-- 引入自定义api通用包-->
<dependency>
    <groupId>com.zqc.springcloud</groupId>
    <artifactId>cloud-api-commons</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

因为这里包含CommonResult类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
    private Integer code;
    private String message;
    private T data;

    public CommonResult(Integer code, String message) {
        this(code, message, null);
    }
}

🔶 新增业务类

@RestController
public class RateLimitController {

    @GetMapping("/byResource")
    @SentinelResource(value = "byResource", blockHandler = "handleException")
    public CommonResult byResource() {
        return new CommonResult(200, "按资源名称限流测试ok",new Payment(2020L, "serial001"));
    }
    public CommonResult handleException(BlockException exception) {
        return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
    }
}

运行微服务并访问:http://localhost:8401/byResource

{"code":200,"message":"按资源名称限流测试ok","data":{"id":2020,"serial":"serial001"}}

🔶 配置规则

在配置规则时,可以使用url(@GetMapping()),也可以使用资源名(@SentinelResource())。

下面,按资源名称流控
在这里插入图片描述
在这里插入图片描述

超过1次/s访问:http://localhost:8401/byResource

{"code":444,"message":"com.alibaba.csp.sentinel.slots.block.flow.FlowException\t 服务不可用","data":null}

如果未设置blockHandler方法,会返回Sentinel自带的限流处理结果。

8.2 面临问题

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

8.3 自定义限流处理逻辑

解决耦合问题,将兜底方法单独放到一个类中。

🔶 自定义限流处理类 CustomerBlockHandler

包含两个自定义的兜底方法,后面将要使用。

public class CustomerBlockHandler {
    public static CommonResult handlerException1(BlockException exception) {
        return new CommonResult(4444, "按客户自定义, global handlerException----------1");
    }

    public static CommonResult handlerException2(BlockException exception) {
        return new CommonResult(4444, "按客户自定义, global handlerException----------2");
    }
}

🔶 新增业务类中的方法

该方法限流后,将调用CustomerBlockHandler类中的handlerException2方法。

@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(
        value = "customerBlockHandler",
        blockHandlerClass = CustomerBlockHandler.class,
        blockHandler = "handlerException2")
public CommonResult customerBlockHandler() {
    return new CommonResult(200, "按客户自定义", new Payment(202L, "serial002"));
}

在这里插入图片描述

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

{"code":200,"message":"按客户自定义","data":{"id":202,"serial":"serial002"}}

🔶 添加限流规则
在这里插入图片描述
🔶 测试

访问超过1次/s:http://localhost:8401/rateLimit/customerBlockHandler

{"code":4444,"message":"按客户自定义, global handlerException----------2","data":null}

九、服务熔断

9.1 建项目测试

新建3个微服务,完成以下的功能,代码在Gitee中,此处不赘述了。
在这里插入图片描述
测试9003访问:http://localhost:9003/paymentSQL/1

{"code":200,"message":"from mysql, serverPort: 9003","data":{"id":1,"serial":"000001"}}

测试9004访问:http://localhost:9004/paymentSQL/1

{"code":200,"message":"from mysql, serverPort: 9004","data":{"id":1,"serial":"000001"}}

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

{"code":200,"message":"from mysql, serverPort: 9003","data":{"id":1,"serial":"000001"}}
或,负载均衡
{"code":200,"message":"from mysql, serverPort: 9004","data":{"id":1,"serial":"000001"}}

9.2 异常处理和配置违规

控制类:

@RestController
public class CircleBreakerController {
    public static final String SERVICE_URL = "http://nacos-payment-provider";

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
    @SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "blockHandler")
    public CommonResult<Payment> fallback(@PathVariable Long id) {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id, CommonResult.class, id);

        if(id==4) {
            throw new IllegalArgumentException("IllegalAccessException, 非法参数异常");
        } else if (result.getData() == null) {
            throw new NullPointerException("NullPointerException, 该id没有对应记录,空指针异常");
        }
        return result;
    }

    // fallback管理运行时异常,相当于hystrix里的服务降级
    public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
        Payment payment = new Payment(id, "null");
        return new CommonResult(444, "兜底异常handlerFallback, exception内容 " + e.getMessage(), payment);
    }

    // blockHandler 管理配置违规,不管异常
    public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {
        Payment payment = new Payment(id, "null");
        return new CommonResult(445, "blockHandler-sentinel限流, 无此流水: blockException " + blockException.getMessage(), payment);
    }
}

配置服务降级规则:
在这里插入图片描述
在这里插入图片描述

访问:http://localhost:84/consumer/fallback/4

前两次:异常处理,调用fallback

后面:在2m内异常2次,配置违规,调用blockHandler

9.3 忽略异常

针对某一类型异常不再使用fallback兜底。
在这里插入图片描述

9.4 整合OpenFeign

🔶 POM依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

🔶 yml配置文件中,激活sentinel对Feign支持

feign:
  sentinel:
    enabled: true

🔶 主启动类添加注解:@EnableFeignClients

🔶 接口+注解:

@FeignClient(value = "nacos-payment-provider", fallback = PaymentFallbackService.class)
public interface PaymentService {

    @GetMapping(value = "/paymentSQL/{id}")
    CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}

🔶 实现接口 fallback

@Component
public class PaymentFallbackService implements PaymentService {
    @Override
    public CommonResult<Payment> paymentSQL(Long id) {
        return new CommonResult<>(44444, "服务降级返回,---PaymentFallbackService", new Payment(id, "errorSerial"));
    }
}

🔶 业务类新增方法:

// ---------------------------OpenFeign-----------
@Resource
private PaymentService paymentService;

@GetMapping("/consumer/openfeign/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
    return paymentService.paymentSQL(id);
}

🔶 测试

访问:http://localhost:84/consumer/openfeign/paymentSQL/1

{"code":200,"message":"from mysql, serverPort: 9003","data":{"id":1,"serial":"000001"}}
或,负载均衡
{"code":200,"message":"from mysql, serverPort: 9004","data":{"id":1,"serial":"000001"}}

关闭 9003和9004

访问:http://localhost:84/consumer/openfeign/paymentSQL/1

{"code":44444,"message":"服务降级返回,---PaymentFallbackService","data":{"id":1,"serial":"errorSerial"}}

十、规则持久化

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

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

步骤:

🔶 POM依赖,将给配置添加到微服务8401(可在Gitee内查看)

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

🔶 YML配置

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080 # 配置sentinel dashboard地址
        port: 8719 # 默认8179端口,如果被占用会自动从8719依次+1扫描,直到找到未被占用的端口
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow
management:
  endpoints:
    web:
      exposure:
        include: '*'
        
feign:
  sentinel:
    enabled: true

🔶 nacos配置
在这里插入图片描述
里面的json

[
    {
        "resource":"/testHotKey",
        "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,多次访问进行测试:http://localhost:8401/testHotKey

可在流控规则内查看到:
在这里插入图片描述

重启微服务将不受影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

望天边星宿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值