十五、SpringCloud Alibaba Sentinel 实现熔断与限流

本文详细介绍了Sentinel的使用,包括Sentinel简介、安装控制台、初始化工程、流控规则、服务降级、热点key限流、系统规则以及服务熔断功能。Sentinel作为阿里巴巴开源的流量控制、熔断降级组件,能有效防止服务雪崩,确保服务稳定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录


一、SpringCloud 微服务基础介绍
二、SpringCloud 微服务项目构建
三、SpringCloud 微服务之Eureka 服务注册与发现
四、SpringCloud 微服务之 Zookeeper 服务注册与发现
五、SpringCloud 微服务之Consul 服务注册与发现
六、SpringCloud 微服务之 Ribbon 负载均衡服务调用
七、SpringCloud 微服务之 OpenFeign 服务接口调用
八、SpringCloud 微服务之 Hystrix 断路器
九、Spring Cloud 微服务之 Gateway
十、SpringCloud 微服务之SpringCloud Config 分布式配置中心
十一、SpringCloud 微服务之SpringCloud Bus 消息总线
十二、SpringCloud 微服务之SpringCloud Stream 消息驱动
十三、Spring Cloud 微服务之 SpringCloud Sleuth 分布式请求链路跟踪
十四、SpringCloud Alibaba Nacos 服务注册和配置中心
十五、SpringCloud Alibaba Sentinel 实现熔断与限流
十六、SpringCloud Alibaba Seata 处理分布式事务

1. Sentinel 简介

1.1 官网:

https://github.com/alibaba/Sentinel
https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

1.2 比较

在这里插入图片描述

1.3 是什么

在这里插入图片描述
在这里插入图片描述

1.4 下载地址

https://github.com/alibaba/Sentinel/releases
在这里插入图片描述

1.5 能干嘛

在这里插入图片描述

1.6 怎么用:解决哪些问题

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

2. 安装Sentinel控制台

2.1 sentinel组件有两部分构成

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

2.2 安装步骤

  1. 下载
    https://github.com/alibaba/Sentinel/releases
  2. 运行
    前提:Java8环境、8080端口没被占用
    命令:java -jar xxx.jar
  3. 访问sentinel管理界面
    http://ip:8080
    登录账号密码均为sentinel
    在这里插入图片描述
    在这里插入图片描述

3. 初始化演示工程

3.1 在父项目中创建 cloud-alibaba-sentinel-service8401 服务module

1. 修改pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.zzx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-alibaba-sentinel-service8401</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- SpringCloud alibaba Nacos discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

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

        <!-- openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </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>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

</project>

2. 编写 yaml

server:
  port: 8401

spring:
  application:
    name: cloud-alibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        # Nacos 服务注册中心地址
        server-addr: 47.107.124.79:8848
    sentinel:
      transport:
        # 配置 sentinel dashboard地址
        dashboard: 47.107.124.79:8080
        # 默认8719端口,假如端口被占用会自动从8719开始一次+1扫描,直到找到未被占用的端口
        port: 8719
        # 当sentinel和微服务不在同一台机器上时,需配置微服务启动机器的ip
        client-ip: 微服务ip
        
management:
  endpoints:
    web:
      exposure:
        include: '*'

4. 编写主启动类和业务类

主启动类

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

业务类 FlowLimitController

@RestController
public class FlowLimitController {

    @GetMapping("/testA")
    public String testA(){
        return "------------testA";
    }

    @GetMapping("/testB")
    public String testB(){
        return "------------testB";
    }
}

5. 启动测试

  • 启动 nacos、Sentinel
  • 启动微服务 8401
  • 启动微服务后查看sentinel控制台
    发现什么也没有,sentinel采用的是懒加载
    在这里插入图片描述
    执行一次访问即可
    在这里插入图片描述
    在这里插入图片描述
    效果:多次访问testA和testB接口,出现下图所示
    在这里插入图片描述

4. 流控规则

4.1 基本介绍

在这里插入图片描述
进一步解释说明:

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

4.2 流控模式

1. 默认直接

直接 -> 快速失败
QPS方式:

  • 添加流控规则
    • 方式一:
      在这里插入图片描述
      在这里插入图片描述
    • 方式二:
      在这里插入图片描述
      在这里插入图片描述
  • 配置说明
    在这里插入图片描述
  • 测试
    点击快速访问 http://localhost:8401/testA
    结果:
    在这里插入图片描述

线程数方式:
在这里插入图片描述

2. 关联

  • 是什么
    1. 当关联的资源达到阈值就限流自己
    2. 当与A关联的资源B达到阙值后,就限流A自己
    3. B惹事,A挂了
  • 配置testA
    在这里插入图片描述
  • postman模拟并发密集访问testB
    创建 Collections 测试
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 测试
    先在postman测试testB可以正常访问,然后Run Sentinel关联测试的Collections集合,然后访问testA
    测试结果:
    在这里插入图片描述
    大批量线程高并发访问B,导致A失效了

3. 链路

-配置 testA
在这里插入图片描述

4.3 流控效果

官网地址:https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6#%E5%9F%BA%E4%BA%8E%E8%B0%83%E7%94%A8%E5%85%B3%E7%B3%BB%E7%9A%84%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6

1. 直接-快速失败

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

2. Warm Up (预热)

官网参考:https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81—%E5%86%B7%E5%90%AF%E5%8A%A8
默认coldFactor为3,即请求QPS从threshold/3开始,经过预热时长逐渐升至设定的QPS阙值。
在这里插入图片描述
在这里插入图片描述

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

3. 排队等待

官网参考:https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6-%E5%8C%80%E9%80%9F%E6%8E%92%E9%98%9F%E6%A8%A1%E5%BC%8F
在这里插入图片描述

  • 注意:匀速排队只允许阈值为QPS模式

5. 服务降级

官网参考:https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7

5.1 基本介绍

在这里插入图片描述
在这里插入图片描述

1. 说明

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

2. Sentinel 断路器

Sentinel的断路器是没有半开状态的
半开的状态系统自动去检测是否请求有异常,没有日常就关闭断路器恢复使用,有异常则继续打开断路器不可用。具体可以参考hystrix

在Sentinel 1.8.0及其以上,引入了半开状态,详情可参考官网
https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7

5.2 降级策略应用

1. 慢调用比例

  • 是什么
    在这里插入图片描述

  • 测试 controller 新增 testD方法

      	@GetMapping("/testD")
      	public String testD() {
          	// 将线程暂停几秒钟
          	try {
              	TimeUnit.SECONDS.sleep(1);
          	} catch (InterruptedException e) {
              	e.printStackTrace();
          	}
          	log.info("-------testD,测试 慢调用比例");
          	return "-------testD";
      	}
    
  • 配置熔断规则
    注意:测试时统计时长尽量设置小一点;eg 100ms
    在这里插入图片描述
    在这里插入图片描述

  • 使用jmeter进行压测
    20个线程,1ms,永远执行
    在这里插入图片描述
    在这里插入图片描述
    设置好后执行
    jmeter使用参考:https://blog.csdn.net/zhou_zhao_xu/article/details/119036090

  • 网页访问测试结果
    在这里插入图片描述

2. 异常比例

  • 是什么
    在这里插入图片描述
  • 新增 controller 方法
        @GetMapping("/testE")
        public String testE() {
            log.info("-------testE,测试 异常比例");
            int age = 10 / 0;
            return "-------testE,测试 异常比例";
        }
    
  • 配置熔断规则
    在这里插入图片描述
  • 测试
    注意:需多次点击测试,要达到触发熔断阈值才会触发
    在这里插入图片描述

3. 异常数

  • 是什么
    在这里插入图片描述
    异常数是按照分钟统计的
  • 新增 controller 方法
        @GetMapping("/testF")
        public String testF() {
            log.info("-------testF,测试 异常数");
            int age = 10 / 0;
            return "-------testF,测试 异常数";
        }
    
  • 配置熔断规则
    在这里插入图片描述
  • 测试
    注意:需多次点击测试,要达到触发熔断阈值才会触发
    在这里插入图片描述

6. 热点key限流

官网参考:https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81

  • 是什么
    在这里插入图片描述

6.1 基本配置使用

  • 新增 controller 方法
    @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) {

        log.info("p1 = {},p2 = {}", p1, p2);
        return "-------testHotkey";

    }

    public String deal_testHotkey(String p1, String p2, BlockException blockException) {
        return "-------deal_testHotkey";
    }
  • 配置热点规则
    在这里插入图片描述
  • 测试
    多次连续点击访问测试会根据上面设置的规则限流,返回自定义处理模块逻辑代码结果,只要携带p1参数,多次连续访问就会限流
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

注意:热点key限流配置,请一定要配置自定义限流处理方法,不然会返回错误页
在这里插入图片描述

6.2 参数例外项

前提条件:热点参数的注意点,参数必须是基本类型或者String

  • 配置
    在这里插入图片描述
  • 测试
    多次连续点击测试,发现当值为5时,未进入限流,当值不为5时,进入限流
    在这里插入图片描述
    在这里插入图片描述

7. 系统规则

官网参考:https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81
在这里插入图片描述

  • 配置全局QPS
    在这里插入图片描述
  • 测试
    一次连续点击每个接口,发现所有的接口都会被限流
    在这里插入图片描述
    在这里插入图片描述

8. @SentinelResource

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

  1. 启动 nacos、sentinel
  2. 修改 8401 模块
    • 引入依赖

            <dependency>
               <groupId>com.zzx</groupId>
              <artifactId>cloud-api-commons</artifactId>
              <version>${project.version}</version>
            </dependency>
      
    • yaml

    • 业务类RateLimitController
      ```java
      @RestController
      public class RateLimitController {

      	@GetMapping("/byResource")
      	@SentinelResource(value = "byResource", blockHandler = "handleException")
      	 public CommonResult byResource() {
        		return new CommonResult(200, "按资源名称限流测试OK", new Payment(2020L, "serial007"));
      	 }
      
      	public CommonResult handleException(BlockException blockException) {
        		return new CommonResult(444, blockException.getClass().getCanonicalName() + "\t服务不可用");
      	}
      
      }
      ```	   	
      
  3. 配置流控规则
    • 配置步骤及图形配置和代码关系
      在这里插入图片描述
    • 表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流
  4. 测试

    连续多次访问此接口,限流后返回自定义信息
    在这里插入图片描述

注意:上面的返回格式不是JSON而是XML格式,这是因为sentinel依赖中包含了 jackson-dataformat-xml 它会将数据默认转换为xml形式,只需要排除对应包中的这个jar包就可以了
在这里插入图片描述
在这里插入图片描述
排除后结果:正常结果和触发流控规则结果
在这里插入图片描述
在这里插入图片描述

8.2 按照URL地址限流+后续处理

在这里插入图片描述
在这里插入图片描述
注意:当使用URL地址限流时,就算自己配置了限流后续响应信息也不会触发,会使用系统默认的

8.3 上面兜底方案面临的问题

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

8.4 客户自定义限流处理逻辑

  1. 创建自定义限流处理类 CustomerBlockHandler 用于自定义限流处理逻辑
    在这里插入图片描述
  2. RateLimitController
    在这里插入图片描述
  3. 启动微服务后先调用一次,使其在sentinel控制台可以找到
    在这里插入图片描述
  4. 配置限流规则
    在这里插入图片描述
  5. 测试
    快速连续点击测试,发现限流后返回了我们自定义的限流响应信息
    在这里插入图片描述
  6. 代码关系
    在这里插入图片描述

8.5 更多注解属性说明

官网参考:https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81
在这里插入图片描述

9. 服务熔断功能

9.1 sentinel整合ribbon

1. 在父项目中创建 cloud-alibaba-provider-payment9003/9004 生产者服务module

9004参考9003

1.1 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.zzx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-alibaba-provider-payment9003</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- SpringCloud alibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </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>

        <dependency>
            <groupId>com.zzx</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>
1.2 编写 yaml 配置
server:
  port: 9003

spring:
  application:
    name: cloud-alibaba-nacos-provider-service

  cloud:
    # Nacos 配置
    nacos:
      discovery:
        server-addr: 47.107.124.79:8848 # 配置 Nacos 地址

# 暴露web端点
management:
  endpoints:
    web:
      exposure:
        include: '*'
1.3 编写启动类和业务类

启动类

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

业务类

@RestController
@Slf4j
public class PaymentController {

    @Value("${server.port}")
    private String serverPort;

    /**
     * 准备测试数据,也可以连数据库测试
     */
    private static Map<Long, Payment> map = new HashMap<>();

    static {
        map.put(1L, new Payment(1L, "serial001"));
        map.put(2L, new Payment(2L, "serial002"));
        map.put(3L, new Payment(3L, "serial003"));
        map.put(4L, new Payment(4L, "serial004"));
    }

    @GetMapping("/paymentSQL/get/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) {
        log.info("Enter {} server,parameter is {}", serverPort, id);
        Payment payment = map.get(id);
        return new CommonResult<Payment>(200, "from mysql,serverPort = " + serverPort, payment);
    }
}
1.4 启动测试
  • 根据给定数据测试
    在这里插入图片描述
    在这里插入图片描述
  • 查看是否注册进nacos中
    在这里插入图片描述

2. 在父项目中创建 cloud-alibaba-nacos-consumer-order84 消费者服务module

注意事项:修改后请手动重启微服务,热部署对注解修改有时不生效

2.1 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.zzx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-alibaba-nacos-consumer-order84</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

        <!-- SpringCloud alibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.2.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.dataformat</groupId>
                    <artifactId>jackson-dataformat-xml</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- SpringCloud alibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </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>

        <dependency>
            <groupId>com.zzx</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>
2.2 编写 yaml 配置文件
server:
  port: 84

spring:
  application:
    name: cloud-alibaba-nacos-consumer-order

  cloud:
    # Nacos 配置
    nacos:
      discovery:
        server-addr: 47.107.124.79:8848 # Nacos 服务注册中心地址
    # Sentinel 配置
    sentinel:
      transport:
        # 配置 sentinel dashboard地址
        dashboard: localhost:8080
        # 默认8719端口,假如端口被占用会自动从8719开始一次+1扫描,直到找到未被占用的端口
        port: 8719
        
# 消费者将要去访问的微服务地址
service-url:
  nacos-user-service: http://cloud-alibaba-nacos-provider-service
2.3 编写启动类、配置类和业务类

启动类

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

配置类

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

自定义全局 fallback 类

public class CustomerFallbackHandler {

    public static CommonResult fallbackHandler(Long id, Throwable throwable) {
        return new CommonResult(500, "id = " + id + " " + throwable.getMessage());
    }

}

自定义全局 sentinel 默认返回信息

public class CustomerBlockHandler {

    public static CommonResult blockHandler(Long id, BlockException blockException) {
        return new CommonResult(444, "id = " + id + " " + blockException.getClass().getCanonicalName());
    }

}

业务类

@RestController
@Slf4j
public class CircleBreakerController {

    @Value("${service-url.nacos-user-service}")
    private String serviceUrl;

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/get/{id}")
    //@SentinelResource(value = "fallback") // 没有配置
    // fallback只负责业务异常
    @SentinelResource(value = "fallback", fallbackClass = CustomerFallbackHandler.class, fallback = "fallbackHandler")
    // blockHandler 只负责 Sentinel 控制台输出
    //@SentinelResource(value = "fallback", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "blockHandler")
    /*@SentinelResource(value = "fallback", fallbackClass = CustomerFallbackHandler.class,  fallback = "handlerFallback",
     blockHandlerClass = CustomerBlockHandler.class, blockHandler = "blockHandler")*/
    public CommonResult<Payment> fallback(@PathVariable("id") Long id) {
        CommonResult<Payment> result = restTemplate
            .getForObject(serviceUrl + "/paymentSQL/get/" + id,
                CommonResult.class, id);
        if (id == 5) {
            throw new IllegalArgumentException("IllegalArgumentException,非法参数异常");
        } else if (result.getData() == null) {
            throw new NullPointerException("NullPointerException,该id没有对应的记录");
        }
        return result;
    }
}
2.4 测试

依次启动9003、9004、84,并查看是否注册进了nacos中
在这里插入图片描述

1. 当没有配置时

在这里插入图片描述
返回信息不友好
在这里插入图片描述
在这里插入图片描述

2. 只配置 fallback时

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 只配置 blockHandler 时
  • 修改代码
    在这里插入图片描述
  • 新增熔断规则
    在这里插入图片描述
  • 多次点击测试
    达到阈值后触发降级限流
    在这里插入图片描述
4. fallback 和blockHandler 都配置
  • 修改代码
    在这里插入图片描述
  • sentinel 对 fallback 新增流控规则
    在这里插入图片描述
  • 启动测试
    在这里插入图片描述
    在这里插入图片描述
  • 注意:若blockHandler和fallback都进行了配置,则被降级限流而抛出BlockException时只会进入blockHandler处理逻辑
5. 忽略属性
  • 修改代码
    在这里插入图片描述
  • 测试
    在这里插入图片描述
  • 结果
    当忽略的一场出现时,不会进入fallback方法,会直接返回给前端

9.2 sentinel整合openFeign

1. 在父项目中创建 cloud-alibaba-nacos-openfeign-consumer-order85 消费者服务module

1.1 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.zzx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-alibaba-nacos-openfeign-consumer-order85</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

        <!-- SpringCloud alibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.2.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.dataformat</groupId>
                    <artifactId>jackson-dataformat-xml</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

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

        <!-- SpringCloud alibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </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>

        <dependency>
            <groupId>com.zzx</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>
1.2 编写 yaml 配置文件
server:
  port: 85

spring:
  application:
    name: cloud-alibaba-nacos-consumer-order

  cloud:
    # Nacos 配置
    nacos:
      discovery:
        server-addr: 47.107.124.79:8848 # Nacos 服务注册中心地址
    # Sentinel 配置
    sentinel:
      transport:
        # 配置 sentinel dashboard地址
        dashboard: localhost:8080
        # 默认8719端口,假如端口被占用会自动从8719开始一次+1扫描,直到找到未被占用的端口
        port: 8719

# 启用 Sentinel 对 feign 的支持
feign:
  sentinel:
    enabled: true
1.3 编写启动类、业务类、自定义fallback、blockHandler、controller

启动类

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

业务类

@FeignClient(value = "cloud-alibaba-nacos-provider-service")
public interface PaymentService {

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

}

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

controller

@RestController
public class CircleBreakerController {

    private final PaymentService paymentService;

    @Autowired
    public CircleBreakerController(PaymentService paymentService) {this.paymentService = paymentService;}

    @GetMapping("/feign/consumer/paymentSQL/get/{id}")
    public CommonResult<Payment> fallback(@PathVariable("id") Long id) {
        CommonResult result = paymentService.paymentSQL(id);
        return result;
    }
}

启动时遇见报错:Caused by: java.lang.AbstractMethodError: com.alibaba.cloud.sentinel.feign.SentinelContractHolder.parseAndValidatateMetadata(Ljava/lang/Class;)Ljava/util/List;
新建包 com.alibaba.cloud.sentinel.feign 添加 SentinelContractHolder
参考:https://blog.csdn.net/zhou_zhao_xu/article/details/119781758

public class SentinelContractHolder implements Contract {

    private final Contract delegate;

    public final static Map<String, MethodMetadata> METADATA_MAP = new HashMap<>();

    public SentinelContractHolder(Contract delegate) {
        this.delegate = delegate;
    }

    @Override
    public List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType) {
        List<MethodMetadata> metadatas = delegate.parseAndValidatateMetadata(targetType);
        metadatas.forEach(metadata -> METADATA_MAP
            .put(targetType.getName() + metadata.configKey(), metadata));
        return metadatas;
    }
}

熔断框架比较

SentinelHystrixResilience4j
隔离策略信号量增高(并发线程数限流)线程池隔离/信号量隔离信号量隔离
熔断降级策略基于响应时间、异常比率、异常数基于异常比率基于异常比率、响应时间
实时统计实现滑动窗口(LeapArray)滑动窗口(基于RxJava)Ring Bit Buffer
动态规则配置支持多种数据源支持多种数据源有限支持
扩展性多个拓展点插件的形式接口的形式
基于注解支持支持支持支持
限流基于QPS,支持基于调用关系的限流有限的支持Rate Limiter
流量整形支持预热模式、匀速器模式、预热排队模式不支持简单的Rate limiter
系统自适应保护支持不支持不支持
控制台提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等简单的监控查看不提供控制台,可对接其它监控系统

10. 规则持久化

  • 是什么
    一旦我们重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化
  • 怎么用
    将限流规则持久化进Nacos保存,只要刷新8402某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8402上sentinel上的流控规则持续有效

持久化应用

1. 在父项目中创建 cloud-alibaba-sentinel-service8402 服务module

1.1 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.zzx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-alibaba-sentinel-service8401</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- SpringCloud alibaba Nacos discovery -->
        <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>com.zzx</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- SpringCloud alibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.2.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.dataformat</groupId>
                    <artifactId>jackson-dataformat-xml</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

</project>
1.2 编写 yaml 配置
server:
  port: 8402

spring:
  application:
    name: cloud-alibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        # Nacos 服务注册中心地址
        server-addr: 47.107.124.79:8848

    sentinel:
      transport:
        # 配置 sentinel dashboard地址
#        dashboard: 47.107.124.79:8080
        dashboard: localhost:8080
        # 默认8719端口,假如端口被占用会自动从8719开始一次+1扫描,直到找到未被占用的端口
        port: 8719
#        client-ip: 42.120.75.130
      datasource:
        dsl:
          nacos:
            server-addr: 47.107.124.79:8848
            dataId: cloud-alibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow
            
management:
  endpoints:
    web:
      exposure:
        include: '*'
1.3 编写启动类、业务类、自定义限流返回信息类

启动类

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

自定义限流返回信息类

public class CustomerBlockHandler {

    public static CommonResult handleException(BlockException blockException) {
        return new CommonResult(2021,
            blockException.getClass().getCanonicalName(),
            "客户自定义 global CustomerBlockHandler handleException");
    }

}

业务类

@RestController
public class RateLimitController {

    @GetMapping("/byResource")
    @SentinelResource(value = "byResource", blockHandler = "handleException")
    public CommonResult byResource() {
        return new CommonResult(200, "按资源名称限流测试OK", new Payment(2020L, "serial007"));
    }

    public CommonResult handleException(BlockException blockException) {
        return new CommonResult(444, blockException.getClass().getCanonicalName() + "\t服务不可用");
    }

    @GetMapping("/rateLimit/byUrl")
    @SentinelResource(value = "byUrl", blockHandler = "handleException")
    public CommonResult byUrl() {
        return new CommonResult(200, "按URL限流测试OK", new Payment(2021L, "serial009"));
    }

    /**
     * 用户自定义限流返回信息
     *
     * @return
     */
    @GetMapping("/customize")
    @SentinelResource(value = "customize",
        blockHandlerClass = CustomerBlockHandler.class,
        blockHandler = "handleException")
    public CommonResult customize() {
        return new CommonResult(200, "按用户自定义OK", new Payment(2021L, "serial010"));
    }

}
1.4 添加 Nacos 配置规则

在这里插入图片描述
在这里插入图片描述

[
    {
        "resource": "/rateLimit/byUrl",
        "limitApp": "default",
        "grade": 1,
        "count": 1,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]

启动8402服务,刷新sentinel发现业务规则有了
在这里插入图片描述

1.5 测试
  • 快速访问测试接口,发现限流规则起作用了
    在这里插入图片描述
  • 停止8402服务,再次查看sentinel
    在这里插入图片描述
  • 再次启动8402服务
    刚启动时sentinel中流控规则还是没有出现,多次调用测试接口
    配置重新出现,持久化验证通过
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值