一、概述
1、介绍
Sentinel("哨兵")是阿里巴巴开源 的分布式系统流量治理组件 ,被誉为 "分布式系统的流量防卫兵"。它以流量为核心切入点,从流量控制、熔断降级、系统负载保护、热点参数防护等多维度保障微服务架构的稳定性,已成为国内微服务生态中高可用保障的主流方案之一。
官方网址
https://sentinelguard.io/zh-cn/GitHub文档地址
https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
2、功能
| 功能模块 | 核心能力 | 典型应用 |
|---|---|---|
| 流量控制 | 限制 QPS / 并发数,控制入口流量,削峰填谷 | 秒杀系统、高并发接口限流 |
| 熔断降级 | 依赖服务异常时快速熔断,降级返回兜底逻辑,避免级联故障 | 第三方接口超时 / 异常容错 |
| 系统自适应保护 | 基于系统负载(CPU/Load/QPS)动态限流,防止系统过载 | 高并发场景系统稳定性保障 |
| 热点参数限流 | 针对热点参数(如商品 ID、用户 ID)精准限流,防护热点击穿 | 热门商品、大促活动场景 |
| 来源访问控制 | 基于调用来源(IP / 应用)进行权限与流量控制 | 内外网接口隔离、白名单控制 |
| 实时监控 | 秒级统计流量、规则命中、系统指标,支持可视化与告警 | 运维监控、故障排查 |
| 规则动态配置 | 支持规则动态下发与热更新,无需重启服务 | 线上流量策略灵活调整 |
二、安装
- 核心库(Java 客户端):轻量级依赖,无框架限制,负责资源定义、流量统计、规则校验与执行。
- 控制台(Dashboard) :可视化管理工具,负责规则配置、监控展示、机器管理、规则持久化 ,默认账号 / 密码为
sentinel/sentinel。
1、下载
下载地址
https://github.com/alibaba/Sentinel/releases
2、运行
需要Java8环境,注意8080端口不要占用
java -jar sentinel-dashboard-1.8.9.jar
或者指定端口
java -Dserver.port=8081 -jar sentinel-dashboard-1.8.9.jar

3、访问


三、限流降级规则
1、工程搭建
(1)创建工程

(2)添加pom
XML
<?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.hk.cloudstudy</groupId>
<artifactId>SecondSpringCloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.hk</groupId>
<artifactId>cloud-sentinel-server8401</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>
<!--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>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- SpringBoot整合Web组件+actuator -->
<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>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.3</version>
</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>
</project>
(3)配置文件
XML
server:
port: 8401
spring:
application:
name: cloud-sentinel-service
cloud:
nacos:
discovery:
#Nacos服务注册中心地址
server-addr: hd01:8848
sentinel:
transport:
#配置Sentinel dashboard地址
dashboard: hd01:8081
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
management:
endpoints:
web:
exposure:
include: '*'
(4)启动类
java
@SpringBootApplication
@EnableDiscoveryClient
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
(5)业务类
java
@RestController
public class FlowLimitController
{
@GetMapping("/testA")
public String testA()
{
return "------testA";
}
@GetMapping("/testB")
public String testB()
{
return "------testB";
}
}
(6)启动
先启动nacos和sentinel,再启动8401服务,第一次查看sentinel是空的,应为sentinel是懒加载,当访问接口后就会出现监控的控制台



2、流控规则
(1)名词解释


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

说明:对/testA资源的访问每秒查询1次,超过1次直接快速失败,抛出默认异常
测试:每秒访问1次是正常的,超过1次出现 Blocked by Sentinel (flow limiting) 错误


2)关联模式

说明:当关联资源/testB达到阀值时,就限流/testA的访问。
一直访问B,同时访问A时出现错误

3)链路模式

testB访问testA, testC也访问testA,那个只会限制testB的访问,不会限制testC的访问
例子:有一个公共方法:
goodsService.getStock()它被两个入口调用:
- 入口 A:
/api/h5/detail(H5 页面,高并发)- 入口 B:
/api/admin/stock(后台管理,低流量)只想限制 H5 页面带来的流量,不想影响后台。就可以给
getStock()设置:
- 流控模式:链路
- 入口资源:
/api/h5/detail只有从 H5 过来的请求会计数并限流,后台调用不受影响。
从指定入口链路进来的流量 → 达到阈值 → 限流
(3)流控效果
1)快速失败

说明:对/testA资源的访问每秒查询1次,超过1次直接快速失败,抛出默认异常
测试:每秒访问1次是正常的,超过1次出现 Blocked by Sentinel (flow limiting) 错误


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

系统初始化的阀值为10 / 3 约等于3,即阀值刚开始为3;然后过了5秒后阀值才慢慢升高恢复到10;
例如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。

3)排队等待
匀速排队,让请求以均匀的速度通过,阀值类型必须设成QPS,否则无效。

/testA每秒1次请求,超过的话就排队等待,等待的超时时间为2000毫秒。
3、降级规则
Sentinel 熔断降级:在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。
(1)名词解释

RT(平均响应时间,秒级)
平均响应时间超出阈值且在时间窗口内通过的请求>=5,两个条件同时满足后触发降级
窗口期过后关闭断路器
RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效)
异常比列(秒级)
QPS >= 5 且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级
异常数(分钟级)
异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级
(2)降级策略
1)RT
平均响应时间(DEGRADE_GRADE_RT):当1s内持续进入5个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以ms为单位),那么在接下的时间窗口(DegradeRule中的timeWindow,以s为单位)之内,对这这个方法的调用都会自动地熔断 (抛出 DegradeException) .
注意Sentinel默认统计的 RT上是4900ms,超出此阈值的都会算作4900ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=xxx来配置。

调用/testC,如果超过200毫秒还没处理完,在未来3秒钟的时间窗口内,断路器打开(保险丝跳闸)微服务不可用。3秒后缓慢请求服务会逐渐可用
testC代码:
java
@GetMapping("/testC")
public String testC()
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "------testC";
}


2)异常比例
异常比例(DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量>=5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule中的count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule中的timewindow,以s为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是[0.0,1.0],代表0%-100%。

每秒请求数大于5,异常数占总请求数的的50%,则服务降级,3秒后如何服务恢复则请求慢慢放开
java
@GetMapping("/testC")
public String testC()
{
int i = 1/0;
return "------testC";
}


JMeter关闭后,服务将慢慢恢复,不在降级,而是报错

3)异常数
异常数(DEGRADE_GRADE_EXCEPTION_CoUNT):当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若timewindow小于60s,则结束熔断状态后仍可能再进入熔断状态。

时间窗口一定要大于等于60秒。
前面5次都是出现error,第6次出现降级错误

4、热点规则
是一种参数级细粒度限流 机制,核心作用是:识别并限制高频访问的 "热点参数值"(如爆款商品 ID、高频用户 ID),防止热点数据打垮缓存或数据库,避免 "缓存击穿 / 穿透 / 雪崩" 等问题。

| 参数 | 含义 | 说明 |
|---|---|---|
| 资源名 | 要限流的方法 / 接口 | 必须与 @SentinelResource 的 value 一致 |
| 参数索引 | 限流的参数位置 | 从 0 开始计数,第一个参数为 0 |
| 单机阈值 | 单个参数值的默认阈值 | 所有未配置例外项的参数值共享此阈值 |
| 统计窗口时长 | 统计时间范围 | 单位:秒,默认 1 秒 |
限流出问题后,都是用sentinel系统默认的提示:Blocked by Sentinel (flow limiting),也可以自定义提示。
1)参所索引限流

对资源/testD的第二个参数进行限流,每秒不能操作3个请求,超过返回"活动过于火爆的提示"。
java
@GetMapping("/testD")
@SentinelResource(value = "testD", blockHandler = "blockHandler_testD")
public String testD(@RequestParam String name, @RequestParam String sex)
{
return "------testD" + name + ":" + sex;
}
public String blockHandler_testD(String name, String sex, BlockException exception){
return "活动过于火爆。。。";
}
@SentinelResource注解的方法参数索引,0代表第一个参数,1代表第二个参数,以此类推
单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。限流后调用blockHandler_testD方法。

2)特殊值限流
上述案例演示了第二个参数当QPS超过1秒3次点击后被限流,但是如果期望name参数当它是某个特殊值时对他进行限流
例如:对name参数为lisi,每秒超过1次点击进行限流,其他值的时候每秒超过3次限流

localhost:8401/testD?name=lisi&sex=f 每秒超过1次进行限流
localhost:8401/testD?name=王五&sex=f 每秒超过3次进行限流
热点参数的注意点,参数必须是基本类型或者String
5、系统规则
是一种全局级别的系统保护机制 ,核心作用是:从系统整体负载出发,监控 CPU、内存、RT、入口 QPS、线程数等核心指标,当系统接近或超过承载能力时,自动触发保护,防止系统被压垮。

| 参数 | 含义 | 取值范围 | 说明 |
|---|---|---|---|
| CPU 使用率 | 系统 CPU 使用率阈值 | 0.0~1.0(1.5.0 + 版本支持) | 超过阈值触发保护 |
| 平均 RT | 所有入口流量的平均响应时间 | ≥0(ms) | 平均 RT 达到阈值触发保护 |
| 入口 QPS | 应用所有入口的总 QPS | ≥0 | 总 QPS 超过阈值触发保护 |
| 线程数 | 应用所有入口的总线程数 | ≥0 | 总线程数超过阈值触发保护 |
| load | 系统 1 分钟负载(仅 Linux 支持) | ≥0 | load1 超过阈值触发保护 |
四、@SentinelResource注解
1、资源名称限流
(1)编写代码
java
@RestController
public class RateLimitController
{
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public String byResource() {
return "访问成功 OK";
}
public String handleException(BlockException exception)
{
return "服务不可用";
}
}
(2)限流配置

(3)测试
1秒访问一次

超过1秒1次

问题:如果将服务8401关闭,则配置的流控规则将都会消失
2、url地址限流
(1)编写代码
java
@GetMapping("/byUrl")
public String byUrl()
{
return "访问成功 OK";
}
(2)配置

(3)测试
超过阈值会出现默认错误

3、自定义限流逻辑
(1)创建自定义限流处理类
java
public class MyBlockHandler {
public static String handleException(BlockException exception){
return "自定义的限流处理信息......MyBlockHandler";
}
}
(2)业务类
java
@GetMapping("/myBlockHandler")
@SentinelResource(value = "myBlockHandler", blockHandlerClass = MyBlockHandler.class, blockHandler = "handleException")
public String customerBlockHandler() {
return "访问成功 OK";
}
(3)配置

(4)测试
超过阈值返回自定义阈值

4、注解属性说明
java
@SentinelResource(
value = "资源名", // 【必填】唯一资源名称
blockHandler = "限流兜底方法", // 流控/热点/系统规则触发的兜底
fallback = "熔断兜底方法", // 熔断/业务异常触发的兜底
exceptionsToIgnore = {} // 忽略的异常,不走降级
)
| 参数 | 作用 | 触发场景 | 方法要求 |
|---|---|---|---|
| value | 资源名称(必填) | 控制台配置规则用 | 唯一标识,建议见名知意 |
| blockHandler | 限流 / 热点 / 系统规则兜底 | 流控、热点、系统保护触发 | 参数 = 原方法 +BlockException |
| fallback | 熔断 / 业务异常兜底 | 慢调用、异常、业务报错 | 参数 = 原方法 +Throwable |
| defaultFallback | 默认通用兜底 | 所有异常 / 熔断通用 | 无参方法 |
| exceptionsToIgnore | 忽略异常 | 指定异常不走 fallback | 异常类数组 |
注意点:
1、兜底方法参数
blockHandler = 原方法参数 + BlockException
fallback = 原方法参数 +
Throwable2、权限
必须是public,全局兜底必须是
static3、返回值
必须和原方法的返回值保持一致
五、熔断服务
1、Ribbon系列
(1)服务提供者
例如:服务提供者84提供了一个接口
java
@GetMapping(value = "/getData/{id}")
public String getData(@PathVariable("id") Long id)
{
return "我是服务提供者84:" + id;
}
(2)服务消费者
1)配置类RestTemplate
java
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
}
2)配置fallback和blockHandler
java
@RestController
@Slf4j
public class MyBreakerController {
// 服务提供者名称
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 String fallback(@PathVariable Long id){
String result = restTemplate.getForObject(SERVICE_URL + "/getData/"+id,String.class,id);
if (id == 4) {
throw new IllegalArgumentException ("非法参数异常....");
}else if (result.getData() == null) {
throw new NullPointerException ("NullPointerException,该ID没有对应记录");
}
return result;
}
public String handlerFallback(@PathVariable Long id,Throwable e) {
return "可能不存在:" + id);
}
public String blockHandler(@PathVariable Long id,BlockException blockException) {
return "blockHandler-sentinel限流, id: " + id);
}
}

若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。
2、Feign系列
(1)服务提供者
例如:服务提供者84提供了一个接口
java
@GetMapping(value = "/getData/{id}")
public String getData(@PathVariable("id") Long id)
{
return "我是服务提供者84:" + id;
}
(2)服务消费者
1)添加pom
XML
<!--SpringCloud openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2)配置文件
XML
server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
#Nacos服务注册中心地址
server-addr: hd01:8848
sentinel:
transport:
#配置Sentinel dashboard地址
dashboard: hd01:8080
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
management:
endpoints:
web:
exposure:
include: '*'
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
3)@FeignClient注解的业务接口
java
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService
{
@GetMapping(value = "/getData/{id}")
public String getData(@PathVariable("id") Long id);
}
4)服务降级实现类
java
@Component
public class PaymentFallbackService implements PaymentService {
@Override
public String getData(Long id){
return "服务降级返回,id: " + id;
}
}
5)业务类
java
@RestController
@Slf4j
public class CircleBreakerController {
@Resource
private PaymentService paymentService;
@GetMapping(value = "/consumer/openfeign/{id}")
public String paymentSQL(@PathVariable("id") Long id)
{
if(id == 4) {
throw new RuntimeException("没有该id");
}
return paymentService.paymentSQL(id);
}
}
6)启动类
添加@EnableFeignClients启动Feign的功能
java
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class OrderNacosMain84 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain84.class, args);
}
}
7)测试
测试84调用服务提供者,故意关闭微服务提供者,看84消费侧自动降级,不会被耗死
六、配置持久化
只要重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化。
下面将限流配置规则持久化进Nacos保存,只要刷新应用某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,sentinel上的流控规则持续有效。
(1)修改工程

(2)修改pom文件
XML
<!--SpringCloud ailibaba sentinel-datasource-nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
(3)修改yml配置文件
添加Nacos数据源配置
spring:
cloud:
sentinel:
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
XML
server:
port: 8401
spring:
application:
name: cloud-sentinel-service
cloud:
nacos:
discovery:
#Nacos服务注册中心地址
server-addr: hd01:8848
sentinel:
transport:
#配置Sentinel dashboard地址
dashboard: hd01:8081
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
datasource:
ds1:
nacos:
server-addr: hd01:8848
dataId: cloud-sentinel-service
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
(4)添加Nacos业务规则配置

resource:资源名称;
limitApp:来源应用;
grade:阈值类型,0表示线程数,1表示QPS;
count:单机阈值;
strategy:流控模式,0表示直接,1表示关联,2表示链路;
controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
clusterMode:是否集群。
(5)测试
重启cloud-sentinel-service,查看规则是否存在,发现规则依然存在
