0. 文档地址

1.中文文档 https://sentinelguard.io/zh-cn/
2.GitHub https://github.com/alibaba/Sentinel

1. 简介

服务挂掉的常见原因
在这里插入图片描述

Sentinel 是阿里巴巴开源的分布式系统的流量防护组件,主要用来做流量控制、熔断降级、系统保护。它的定位类似于 Hystrix,但更侧重在 流量治理 上。目前在微服务、服务网关、大型分布式系统中广泛使用,Spring Cloud Alibaba 体系中也自带集成。

=======================================================

🌟 Sentinel 的核心功能

1.流量控制(限流)

  • 可以针对 QPS(每秒请求数)、并发线程数、调用关系等维度设置阈值。
  • 支持 匀速排队、预热模式、冷启动模式 等策略,避免突发流量冲击。

2.熔断降级

  • 根据 异常比例、异常数、响应时间 等指标,对调用链路进行熔断。
  • 熔断后会在一段时间内快速失败,避免故障蔓延。

3.系统保护

  • 基于 系统整体负载(如 CPU 使用率、RT、线程数) 进行自适应保护。
  • 防止因为单个服务请求过多而导致整个系统雪崩。

4.实时监控

  • 提供 控制台,可以实时查看各个服务的限流、熔断、请求量、响应时间等信息。

====================================================

📚 Sentinel 的工作原理

核心是 对请求进行统计与规则判断:

  1. 请求进入时,Sentinel 先判断是否超出阈值。
  2. 如果超出,直接拦截(触发限流/熔断)。
  3. 如果没有超出,就继续放行。

规则可以在 代码中硬编码,也可以通过 动态配置(Nacos、Apollo、ZooKeeper 等) 来下发。

=====================================================

✅ Sentinel 的优势

  • 轻量级,不依赖重量级框架,接入成本低。
  • 功能全面:限流 + 熔断 + 系统保护 + 实时监控。
  • 动态规则:可结合配置中心(Nacos、Apollo 等)。
  • 生态完善:已集成 Spring Cloud、Dubbo、gRPC、Spring WebFlux 等主流框架。

2. 服务雪崩

比如一个电商系统是微服务系统,它包含了秒杀商品、商品详情、购物车、积分等服务,且服务之间也是相互调用的。
在这里插入图片描述
如果其中一个服务挂了,比如说秒杀开始了,积分服务因为性能问题,挂了。

在这里插入图片描述

后续的话,因为积分服务挂掉了,后续的用户请求到积分的时候,所有的请求都会积压到这里,得不到响应。会重复请求导致服务压力更大。然后后面的请求又会积压到商品服务,慢慢的商品服务也挂掉了,后面整条链路的服务都会挂掉。这就是服务雪崩。
在这里插入图片描述
补充:服务挂掉的原因,如激增流量、不稳定服务依赖等等。
在这里插入图片描述

3. Sentinel与Hystrix对比

在这里插入图片描述

4. 流控规则基础

Sentinel可以简单分为Sentinel核心库和Dashboard。核心库不依赖Dashboard,但是结合Dashboard可以取得最好的效果。

Sentinel可以对资源进行保护,资源可以是一段代码,服务、服务里面的方法等。 主要的步骤分为:

  1. 定义资源
  2. 定义规则
  3. 检验规则是否生效

先把可能需要保护好的资源定义好(埋点),之后再配置规则。可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护就定义为一个资源。

4.1 初体验Sentinel

新建一个项目模块sentinel-demo
在这里插入图片描述

其中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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.beijing</groupId>
        <artifactId>springcloudalibaba</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>sentinel-demo</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
            <version>1.8.6</version>
        </dependency>

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

    </dependencies>

</project>

接口:

package com.beijing.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * @author fanzhen@ict.ac.cn
 * @version 1.0
 * @date 2025/09/08
 */
@Slf4j
@RestController
public class HelloController {

    private static final String RESOURCE_NAME = "hello";
    private static final String USER_RESOURCE_NAME = "user";
    private static final String DEGRADE_RESOURCE_NAME = "degrade";

    /**
     * 惊醒流量控制
     *
     * @return String
     */
    @RequestMapping("/hello")
    public String hello() {
        Entry entry = null;

        try {
            // sentinel对资源进行限制
            entry = SphU.entry(RESOURCE_NAME);
            // 被保护的业务逻辑
            String str = "hello world";
            log.info("===============" + str + "===============");
            return str;
        } catch (BlockException e) {
            return "被流控了";
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }

    /**
     * 定义规则
     */
    @PostConstruct
    private static void initFlowRules() {
        // 流控规则
        List<FlowRule> rules = new ArrayList<>();

        // 流控
        FlowRule rule = new FlowRule();
        // 设置受保护的资源
        rule.setResource(RESOURCE_NAME);
        // 设置流控规则QPS
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置受保护的资源阈值
        rule.setCount(1);

        rules.add(rule);

        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);
    }

}

这里通过@PostConstruct注解在项目启动的时候,执行了initFlowRules()方法,该方法定义了规则,包括受保护的资源,流控规则、阈值等。
当在1秒内超过1次调用该接口,返回结果就是 被流控了
在这里插入图片描述

4.2 注解@SentinelResource

上面的代码,可以看到非常的麻烦,而且给人的感觉,侵入性很强。

这个注解的源码:

/*
 * Copyright 1999-2020 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.csp.sentinel.annotation;

import com.alibaba.csp.sentinel.EntryType;

import java.lang.annotation.*;

/**
 * The annotation indicates a definition of Sentinel resource.
 *
 * @author Eric Zhao
 * @author zhaoyuguang
 * @since 0.1.1
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {

    /**
     * @return name of the Sentinel resource
     */
    String value() default "";

    /**
     * @return the entry type (inbound or outbound), outbound by default
     */
    EntryType entryType() default EntryType.OUT;

    /**
     * @return the classification (type) of the resource
     * @since 1.7.0
     */
    int resourceType() default 0;

    /**
     * @return name of the block exception function, empty by default
     */
    String blockHandler() default "";

    /**
     * The {@code blockHandler} is located in the same class with the original method by default.
     * However, if some methods share the same signature and intend to set the same block handler,
     * then users can set the class where the block handler exists. Note that the block handler method
     * must be static.
     *
     * @return the class where the block handler exists, should not provide more than one classes
     */
    Class<?>[] blockHandlerClass() default {};

    /**
     * @return name of the fallback function, empty by default
     */
    String fallback() default "";

    /**
     * The {@code defaultFallback} is used as the default universal fallback method.
     * It should not accept any parameters, and the return type should be compatible
     * with the original method.
     *
     * @return name of the default fallback method, empty by default
     * @since 1.6.0
     */
    String defaultFallback() default "";

    /**
     * The {@code fallback} is located in the same class with the original method by default.
     * However, if some methods share the same signature and intend to set the same fallback,
     * then users can set the class where the fallback function exists. Note that the shared fallback method
     * must be static.
     *
     * @return the class where the fallback method is located (only single class)
     * @since 1.6.0
     */
    Class<?>[] fallbackClass() default {};

    /**
     * @return the list of exception classes to trace, {@link Throwable} by default
     * @since 1.5.1
     */
    Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};
    
    /**
     * Indicates the exceptions to be ignored. Note that {@code exceptionsToTrace} should
     * not appear with {@code exceptionsToIgnore} at the same time, or {@code exceptionsToIgnore}
     * will be of higher precedence.
     *
     * @return the list of exception classes to ignore, empty by default
     * @since 1.6.0
     */
    Class<? extends Throwable>[] exceptionsToIgnore() default {};
}

分析源码

基础信息

@Target({ElementType.METHOD, ElementType.TYPE})    // 可以加在方法或类上
@Retention(RetentionPolicy.RUNTIME)                // 运行时可反射获取
@Inherited                                         // 子类会继承父类的注解
public @interface SentinelResource { ... }
  1. value String value() default ""; 资源的唯一标识名,相当于给这个方法打一个 Sentinel 的 “资源点标签”。
@SentinelResource("getUserInfo")
public User getUserInfo(Long id) { ... }
  1. entryType EntryType entryType() default EntryType.OUT;
    表示资源调用的类型:

    • IN:入口资源(入口流量,如请求进入服务)
    • OUT:出口资源(调用下游依赖,比如数据库、HTTP API)
      默认 OUT。
  2. resourceType 自定义资源分类(数字表示),默认 0

  3. blockHandler / blockHandlerClass

String blockHandler() default "";
Class<?>[] blockHandlerClass() default {};
- blockHandler:指定一个方法名,当资源触发限流、熔断等规则时,会调用这个方法来兜底。
- blockHandlerClass:指定方法所在的类(必须是 static 方法),否则默认在本类里找。
@SentinelResource(value = "getUser", blockHandler = "handleBlock")
public User getUser(Long id) { ... }

public User handleBlock(Long id, BlockException ex) {
    return new User("default");
}
  1. fallback / fallbackClass
String fallback() default "";
Class<?>[] fallbackClass() default {};
- fallback:当方法抛出异常时,会进入 fallback 方法兜底。
- fallbackClass:指定 fallback 方法所在的类(方法必须 static)。
- fallback 方法签名必须与原方法兼容,最后多一个 Throwable 参数也可以。
  1. defaultFallback String defaultFallback() default "";

    • 定义全局兜底方法,不带参数,返回值要和原方法兼容。
    • 优先级低于 fallback。
  2. exceptionsToTrace / exceptionsToIgnore

Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};
Class<? extends Throwable>[] exceptionsToIgnore() default {};
- exceptionsToTrace:哪些异常会触发 fallback,默认是所有异常 (Throwable)。
- exceptionsToIgnore:哪些异常不触发 fallback,会直接抛出。 优先级更高,即忽略列表里的异常不会触发 fallback。

总结
@SentinelResource 主要作用:

  1. 标记资源点(value、entryType、resourceType)。
  2. 定义限流/熔断时的处理逻辑(blockHandler)。
  3. 定义异常时的兜底逻辑(fallback、defaultFallback)。
  4. 灵活控制异常是否进入兜底(exceptionsToTrace / exceptionsToIgnore)。

4.2.1 使用这个注解

 		<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-annotation-aspectj</artifactId>
            <version>1.8.0</version>
        </dependency>

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

重点看代码中的注释

 /**
     * 定义规则
     */
    @PostConstruct
    public void initFlowRules() {
        // 流控规则
        List<FlowRule> rules = new ArrayList<>();

        // 流控
        FlowRule rule = new FlowRule();
        // 设置受保护的资源
        rule.setResource(RESOURCE_NAME);
        // 设置流控规则QPS
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置受保护的资源阈值
        rule.setCount(1);

        FlowRule rule2 = new FlowRule();
        // 设置受保护资源
        rule2.setResource(USER_RESOURCE_NAME);
        // 设置流控规则QPS
        rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule2.setCount(1);

        rules.add(rule);
        rules.add(rule2);

        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);

        System.out.println("当前已加载的流控规则: " + FlowRuleManager.getRules());
    }

    /**
     * sentinelResource 改善接口中资源定义和被流控降级后的处理方法
     * 怎么使用: @SentinelResource(value = "user", blockHandler = "blockHandlerFor")
     * value: 定义资源
     * blockHandler: 降级处理方法(默认该方法必须在同一个类中)
     * <p>
     * ================
     * 如果不想在同一个类中,可以设置blockHandlerClass
     * <p>
     * fallback: 接口出现异常的时候交给fallback指定的方法
     * <p>
     * blockHandler与fallback如果都指定了,则blockHandler优先级更高
     * exceptionsToIgnore 指定哪些异常不处理
     *
     * @return String
     */
    @RequestMapping("/user")
    @SentinelResource(value = USER_RESOURCE_NAME, blockHandler = "blockHandlerForGetUser")
    public User user() {
        return new User("xushu");
    }

    /**
     * 1.这个方法一定要是public
     * 2. 返回值一定要和源方法保证一致,包含源方法的参数,参数的顺序也要一致。
     * 3.可以在参数最后的BlockException
     *
     * @param id
     * @param ex
     * @return
     */
    public User blockHandlerForGetUser(BlockException ex) {
        return new User("被流控了");
    }

4.3 降级规则初体验

可以通过页面配置,也可以在代码中配置。

页面效果
在这里插入图片描述

在这里插入图片描述

代码中的配置

  /**
     * 熔断降级规则初始化
     */
    @PostConstruct
    public void initDegradeRule() {
        List<DegradeRule> degradeRules = new ArrayList<>();
        DegradeRule degradeRule = new DegradeRule();

        degradeRule.setResource(DEGRADE_RESOURCE_NAME);

        // 使用异常比例熔断
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
        degradeRule.setCount(0.5); // 超过 50% 异常率触发熔断
        degradeRule.setMinRequestAmount(2); // 至少两个请求才统计
        degradeRule.setStatIntervalMs(10 * 1000); // 10 秒统计窗口
        degradeRule.setTimeWindow(5); // 熔断 5 秒

        degradeRules.add(degradeRule);
        DegradeRuleManager.loadRules(degradeRules);

        log.info("已加载熔断降级规则: {}", DegradeRuleManager.getRules());
    }

    /**
     * 模拟熔断接口
     */
    @RequestMapping("/degrade")
    @SentinelResource(
            value = DEGRADE_RESOURCE_NAME,
            entryType = EntryType.IN,
            blockHandler = "blockHandlerForFb",
            fallback = "fallbackForFb"
    )
    public User degrade(String id) {
        log.error("触发异常统计");
        throw new RuntimeException("业务异常触发熔断统计");
    }

    /**
     * 熔断后的 blockHandler(规则触发时进入)
     */
    public User blockHandlerForFb(String id, BlockException ex) {
        log.warn("/degrade 被熔断,直接进入 blockHandler: {}", ex.toString());
        return new User("接口已被熔断降级");
    }

    /**
     * 业务异常 fallback(接口内部异常时进入)
     */
    public User fallbackForFb(String id, Throwable ex) {
        log.error("/degrade 出现业务异常,进入 fallback: {}", ex.toString());
        return new User("接口触发业务异常,执行 fallback 兜底");
    }

package com.beijing;

import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author xxx
 * @version 1.0
 * @date 2025/09/11
 */
@Configuration
public class SentinelAspectConfiguration {

    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

<?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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.beijing</groupId>
        <artifactId>springcloudalibaba</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>sentinel-demo</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
            <version>1.8.6</version>
        </dependency>

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

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-annotation-aspectj</artifactId>
            <version>1.8.0</version>
        </dependency>

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

    </dependencies>

</project>

在这里插入图片描述

4.4 Sentinel控制台部署

这里通过docker来安装的,默认的账号与密码都是sentinel

拉取镜像:
docker pull bladex/sentinel-dashboard

启动
docker run --name sentinel -d -p 8858:8858 -d bladex/sentinel-dashboard

访问
http://公网ip:8858

注意:这里有坑
如果Sentinel与你的Java项目不在同一个环境下是连接不上的。

还有记得加启动参数

在这里插入图片描述

4.5 Spring Cloud Alibaba 整合Sentinel

  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
                             https://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.beijing</groupId>
    <artifactId>springcloudalibaba</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloudalibaba</name>
    <description>springcloudalibaba</description>
    <packaging>pom</packaging>

    <modules>
        <module>order</module>
        <module>stock</module>
        <module>order-openFeign</module>
        <module>config-nacos</module>
        <module>sentinel-demo</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.2.RELEASE</spring-boot.version>
        <spring-cloud-alibaba-dependencies.version>2.2.5.RELEASE</spring-cloud-alibaba-dependencies.version>
        <spring-cloud-dependencies.version>Hoxton.SR8</spring-cloud-dependencies.version>
        <lombok.version>1.18.36</lombok.version>
    </properties>

    <dependencies>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba-dependencies.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud-dependencies.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>com.study.springcloudalibaba.springcloudalibaba.SpringcloudalibabaApplication</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

  1. 添加yml配置,为微服务设置sentinel控制台地址
    在这里插入图片描述

4.6 Sentinel控制台规则配置详解

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

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

4.7 并发线程数的流控规则

并发数控制用于保护业务线程池不被慢调用耗尽。例如,当应用所依赖的下游应用由于某种原因导致服务不稳定、响应延迟增加,对于调用者来说,意味着吞吐量下降和更多线程数占用,极端情况下甚至是线程池耗尽。为应对太多线程占用情况,业内有使用隔离的方案,比如通过不同业务逻辑使用不同线程池来隔离自身之间的资源抢争(线程隔离)。这种隔离方案虽然隔离性比较好,但是代价就是线程数目太多,线程上下文奇幻的overhead比较大,特别是对低延时的调用有比较大的影响。

Sentinel并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。并发数控制通常在调用端配置。

在这里插入图片描述

在这里插入图片描述

4.8 BlockException统一异常处理

SpringWebMvc接口资源限流入口在HandlerInterceptor的实现类AbstractSentinelInterceptor的preHandle方法中,对异常的处理是BlockExceptionHandler的实现类。

sentinel 1.7.1 引入了引入了sentinel-spring-webmvc-adapter.jar

自定义BlockExceptionHandler的实现类统一处理BlockException

在这里插入图片描述

在这里插入图片描述

5. 关联流控模式

流控模式有三种分别是:直接、关联、链路。

在这里插入图片描述
直接是默认的方式,如果这个接口的调用超过了指定的QPS或者线程数就直接处理了。受影响的就是这个资源。
关联比如下面的/order/add这个接口,如果这个接口的QPS或者线程数超过阈值,那么我们自己的资源sentonel_default_context就会收到影响。

在这里插入图片描述

链路就是sentonel_default_context这个接口QPS或者线程数超过阈值,那么/order/add就会收到影响。
在这里插入图片描述

链路流控模式

注意:
1.需要配置 spring.cloud.sentinel.web-context-unify: false
2.如下图
在这里插入图片描述

6. 流控效果

流控效果有快速失败、Warm Up、排队等待
在这里插入图片描述

  • 快速失败: 就是直接拒绝。

  • Warm Up(预热): 可以设置一个预热时间,然后请求慢慢的进来。
    在这里插入图片描述

  • 排队等待: 当请求速率超过阈值时,新的请求不会被立刻拒绝,而是进入一个“虚拟队列”。Sentinel 会按照 固定的速率 处理请求,让流量平滑地进入系统。这类似 漏桶算法 (Leaky Bucket),保证请求不会突然冲击后端,而是匀速通过。
    超时时间:如果请求排队等待的时间超过了这个值,就会被直接拒绝。
    在这里插入图片描述

7. 预热流控效果(激增流量)

Warm Up方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加的时,直接把系统拉升到高水位可能瞬间把系统打垮。通过“冷启动”,让通过的流量缓慢增加,在一定时间内主键增加到阈值上限,给系统一个预热的时间,避免冷系统被打垮。

冷加载因子:codeFactor默认是3,即请求QPS从threshold/3开始,经预热时长逐渐升至设定的QPS阈值。

通常冷启动的过程系统允许通过的QPS曲线如下图所示。
在这里插入图片描述

在这里插入图片描述

8. 排队等待(脉冲流量)

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

作业方式
在这里插入图片描述

这种方式主要用于处理间隔性突发的流量。例如消息队列,某一秒有大量的请求到来,而接下来几秒处于空闲状态,我们希望能够在接下来的空闲时间逐步处理,而不是在第一秒就直接拒绝。

在这里插入图片描述
比如一次请求是10个线程,QPS为10,每次最多执行5个,每次执行完1个后面进1个,但是如果同时5个都没有执行完,并且等待超过了5秒,会报超时。

9. 熔断降级规则

除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。我们不需要对不稳定的弱依赖服务调用,进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体雪崩。熔断降级作为保护自身的手段,在客户端进行配置。


熔断降级通常在消费者端

在这里插入图片描述


触发熔断后的处理逻辑示例

  • 提供fallback实现(服务降级)
  • 返回错误result
  • 读缓存(DB 访问降级)

Logo

更多推荐