随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从={yellow}流量控制、熔断降级、系统负载保护=等多个维度保护服务的稳定性。
定义={green}资源=:
- 主流框架={orange}自动适配=
- ={orange}编程式=:SphU API
- ={orange}声明式=:@SentinelResource
定义={green}规则=:
- 流量控制(FlowRule)
- 熔断降级(DegradeRule)
- 系统保护(SystemRule)
- 来源访问控制(AuthorityRule)
- 热点参数(ParamFlowRule)
工作原理

一、安装
引入 sentinel 依赖:
pom
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
yml文件添加sentinel相关配置:
yml
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址
eager: true # sentinel提前加载,默认是懒加载,这里主要是为了方便演示和学习;生产环境不要这样搞
查看sentinel控制台
发现已经监控到了我们服务

二、控制规则

限制多余请求,从而保护系统资源不被耗尽
1、流控规则
调用关系包括调用方、被调用方;一个方法又可能会调用其他方法,形成一个调用链路的层次关系;有了调用链路的统计信息,我们可以衍生出多种流量控制手段。
1.1、流控规则的各个属性

- 资源名: 唯一名称,默认请求路径,表示对该资源进行流控
- 针对来源: Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
-
- 阈值类型/单击阈值:
QPS:(每秒钟的请求数量):当调用该api的QPS达到阈值时,进行限流
线程数:当调用该线程数达到阈值的时候,进行限流
- 阈值类型/单击阈值:
添加后,流控规则之后,快速访问接口查看效果,默认的错误页:

高级选项
流控模式
- 直接(默认)

- 关联

当关联的资源 ={green}写= 达到阈值时,限流自己 ={red}读=
- 链路

这个需要配置一下 yml:
yml
sentinel:
transport:
dashboard: 192.168.88.139:8858
eager: true
web-context-unify: false # 分割统一web的上下文,默认为true
流控效果
={red}注意:=只有
快速失败支持流控模式(直接、关联、链路)的设置也就是说
Warm Up和排队等待不支持关联和链路
-
快速失败

-
Warm Up (预热/冷启动)

效果类似,逐步提升自己的峰值,慢慢提升自己的qps
-
匀速排队

-
QPS:代表 每秒并行的消息 -
timeout:代表 最长等待时间
2、熔断规则
- 切断不稳定调用
- 快速返回不积压
- 避免雪崩效应
最佳策略: 熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。
所以熔断肯定是在服务间调用 的地方配置的

1. 熔断器的三种状态 (State Machine)

理解熔断规则,首先要理解熔断器的工作状态流转:
-
CLOSED (关闭状态):
- 初始状态。请求正常通过,Sentinel 会在后台统计指标(响应时间、异常比例等)。
-
OPEN (打开/熔断状态):
- 当统计指标超过设定的阈值,熔断器进入 OPEN 状态。
- 行为: 在接下来的
熔断时长 (TimeWindow)内,所有请求都会直接被拒绝(抛出DegradeException),不再调用后端服务。
-
HALF-OPEN (半开状态):
- 当
熔断时长结束后,熔断器尝试进入 HALF-OPEN 状态。 - 行为: 允许一次 请求通过。
- 如果该请求成功:熔断器关闭 (CLOSED),恢复正常。
- 如果该请求失败:熔断器再次打开 (OPEN),并重新开始计时。
- 当
2. 三种熔断策略 (Strategies)

在 Sentinel 控制台中,配置熔断规则时有三个核心策略:
A. 慢调用比例 (Slow Call Ratio)
适用场景: 服务没挂,但是响应非常慢,导致调用方线程池耗尽。
-
判断逻辑:
- 你需要定义什么是"慢调用":比如响应时间 (RT) > 200ms。
- 在统计时长内,如果请求总数 >= 最小请求数 ,且 慢调用的比例 超过设定的阈值。
-
关键参数:
- 最大 RT (Count): 设置为 200ms。超过这个时间的请求被记为"慢调用"。
- 比例阈值: 范围 0.0 ~ 1.0。比如 0.6 代表 60%。
- 熔断时长: 熔断触发后持续多久。
B. 异常比例 (Exception Ratio)
适用场景: 服务逻辑报错,或者网络连接异常。
-
判断逻辑:
- 在统计时长内,如果请求总数 >= 最小请求数。
- 异常请求的比例 超过设定的阈值。
-
关键参数:
- 比例阈值 (Count): 范围 0.0 ~ 1.0。比如 0.5 代表 50% 的请求都报错了。
- 注意: 业务代码显式抛出的异常才算,被 Sentinel 限流抛出的 BlockException 不算。
C. 异常数 (Exception Count)
适用场景: 请求量非常少(QPS 很低),用比例不准确时使用。
- 判断逻辑:
- 在统计时长内,异常请求的数量 超过设定的具体数值。
- 关键参数:
- 异常数 (Count): 比如设置为 5。表示只要出错 5 次就熔断。
避坑指南 - 最小请求数 (minRequestAmount): 假设你设置了"异常比例 50%",如果不设置最小请求数(默认为 5),当 1 秒内只有 1 个请求且报错了,异常比例就是 100%,直接熔断。这显然不合理。 建议: 设置为 5 或 10,即只有当并发量达到一定程度且错误率高时,才触发熔断。
3、热点规则
热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的数据,并对其访问进行限制,比如对某个商品id进行限制,或者对某个用户id进行限制
3.1、热点规则属性
参数索引:方法中参数的索引第几个参数
单机阈值:每秒达到单机阈值的数量就会触发兜底方法
案例
新建一个热点规则
我们先创建一个测试方法,使用注解资源名称的形式,并创建自定义兜底方法
java
/**
* 测试centinel热点规则限流
* @param userId
* @param shopId
* @return
*/
@GetMapping("/hotspot")
@SentinelResource(value = "hotspotResource" , blockHandler = "hotspotResource", blockHandlerClass = UserSentinelResourceHandler.class)
public String hotspot(@RequestParam(value = "userId" ,required = false) String userId,
@RequestParam(value = "shopId" ,required = false) String shopId){
System.out.println("我是hotspot");
return "我是hotspot";
}
兜底方法
java
public static String hotspotResource(String userId, String shopId,BlockException blockException){
System.out.println("您被认为恶意访问,触发热点限流");
return "您被认为恶意访问,触发热点限流";
}
然后我们在控制台新建热点规则

其中参数索引 0 代表的就是userId这个参数
我们访问一下接口 先访问带shopId的(一秒内多次访问)
- 正常返回

再访问下带userId参数的(一秒内多次访问)

三、异常处理

1、Web接口

创建一个 exception 的文件

java
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void handle(HttpServletRequest httpServletRequest,
HttpServletResponse response,
String s, BlockException e) throws Exception {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
R error = R.error(500, e.getMessage());
String json = objectMapper.writeValueAsString(error);
writer.write(json);
writer.flush();
writer.close();
}
}
- ={red}注意=:import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler; 不要引入错误了
2、@SentinelResource

fallback:用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了execptionsToIgnore 里面排除掉的异常类型)进行处理,函数要求为:
- 返回类型与原方法一致
- 参数类型需要和原方法相匹配,Sentinel 1.6版本之后,也可在方法最后加上
BlockException类型的参数 - 默认需和原方法在同一个类中,若希望使用其他类的函数,可配置fallbackClass,并指定fallbackClass里面的方法
java
@SentinelResource(value = "createOrder", blockHandler = "createOrderFallback")
@Override
public Order createOrder(Long userId, Long productId) {
// Product product = getProductFromRemote(productId);
Product product = productFeignClient.getProductById(productId);
Order order = new Order();
order.setId(1L);
// 总金额
order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));
order.setUserId(userId);
order.setNickName("kkl-sqm");
order.setAddress("库库林-沙琪马");
// TODO 远程查询商品列表
order.setProductList(List.of(product));
return order;
}
// 兜底回调
public Order createOrderFallback(Long userId, Long productId, BlockException e) {
Order order = new Order();
order.setId(0L);
order.setTotalAmount(new BigDecimal("0"));
order.setUserId(userId);
order.setNickName("未知用户");
order.setAddress("异常信息:" + e.getMessage());
return order;
}
如果不指定 blockHandler ,则 会让异常上抛到全局异常,又项目的 springboot 的全局异常处理器来处理
3、OpenFeign调用

这里是根据OpenFeign的 fallback 来实现的,和 上面的一样,如果不配置 fallback 异常会上抛,被全局异常处理