Sentinel
1. 官网
https://sentinelguard.io/zh-cn/docs/quick-start.html
2. 概念
2.1. 核心库(java客户端)
2.2. 控制台(Dashboard)
服务端,管理推送规则、监控、管理机器信息。
2.3. 熔断规则
2.3.1. 熔断策略
-
并发数
-
慢调用比例
在“统计时长”1秒内,至少有5个请求,有“比例阈值”3个请求,“最大RT”响应时间达到了2秒,则会开始熔断,“熔断时长”10s,第11秒开始接受新请求,
请求成功,则结束熔断,否则再次熔断10s。
-
异常比例
在“统计时长”1秒内,接受请求数超过了“最小请求数”20,这20个请求中“比例阈值(0-1)”异常请求比例达到50(按100%)即20个,则会开始熔断10秒。
2.4. 流控规则
2.4.1. 影响流控效果得关键因素
- resource 资源名,Controller得uri,其它方法上需要显示指定
- count 限流阈值
- grade 限流类型,QPS和线程数
- strategy 策略
2.4.2. 资源名
- 默认为uri,示例:/order/info
2.4.3. 阈值类型
2.4.3.1. 基于QPS/并发数得流量控制
- 默认处理逻辑在DefaultBlockExceptionHandler
public class DefaultBlockExceptionHandler implements BlockExceptionHandler {
public DefaultBlockExceptionHandler() {
}
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
response.setStatus(429);
PrintWriter out = response.getWriter();
out.print("Blocked by Sentinel (flow limiting)");
out.flush();
out.close();
}
}
2.4.3.1.1. 自定义处理
- 也实现BlockExceptionHandler
重写handle();
2.4.4. 针对来源
-
1: 配置参数
-
2:定义解析规则,实现RequestOriginParser
-
3:请求中按找代码的设计传值
http://ip:8080/order?userId=fox
2.4.5. 流控模式
2.4.5.1. 直接
- 定义
配的“资源名”接受请求达到阈值,则触发流控。
2.4.5.2. 关联
- 定义
在a资源页面配置,当资源b,达到阈值,触发的是自身资源a进行流控,资源b不流控。
当关联资源/order/getOrderById/3达到阈值极限,的同时访问/order/getOrder会触发限流。
- 使用场景
写请求流量很大时,限流查询请求。
2.4.5.3. 链路
*定义
在c资源页面配置,有a和b在同时调用c,如果设置了“入口资源”为a,当c达到阈值,对入口资源a进行流控,而不会对b进行流控。
如图,当/test2/3,达到阈值后,会触发限流。
- 问题
调用/test2接口,里面调和不调getOrderById,2种试一下,看看效果 - 入口资源
阈值作用的uri。
*yml配置
从1.6.3开始,Sentinel Web filter默认收敛所有URL的入口context,导致链路限流不生效。
从1.7.0开始,官方在CommonFilter引入了webContextUnify属性,用于控制,设为false,才可生效。
意思就是1.6.3~1.7.0之间无法使用链路限流
1.8.6版本可以在yml中配置
哪些版本可以在yml中配置需要查询官方资料
spring.cloud.sentinel.web-context-unify=false
2.4.6. 流控效果
2.4.6.1. 快速失败
- 含义
直接拒绝的意思,达到阈值后,新的请求直接拒绝并抛出FlowException异常。
2.4.6.2. Warm Up
- 含义
预热,冷启动的意思 - 预热时长
配合冷加载因子,请求需要延迟的x秒才逐渐达到最大阈值。 - 冷加载因子
codeFactor 默认为3,即QPS从1/3开始,需要经过“预热时长”才逐渐达到最大阈值。 - 配置示例,QPS瞬时请求就是20,当时服务会从3慢慢的接受到10,其余被拒绝。
2.4.6.3. 等待排队
- 含义
入队等待的意思,用到了漏桶算法,用的时间轴方式,当QPS阈值为100,则每10毫秒只处理一个请求。 - 注意点
该模式时,QPS > 1000,可自测下什么效果。 - 超时时间(毫秒)
服务接受到请求,开始计时,达到此时间,则拒绝请求。
2.5. 实时监控
- 实时监控仅存储5分钟以内数据,如果要持久化,需要通过调用实时监控接口MetricsRepository 自己实现。
- sentinel控制台服务和监控的微服务之间得时间需一致,不然可能拉取不到数据!
2.6. 簇点链路
- 展示当前服务有哪些资源(url)
2.7. 热点规则
- 作用
自动监控,将该uri自动触发升级为限流接口
2.7.1. 注意点
- 1:代码需要显式添加@SentinelResource,否则不生效
- 2:参数必须是7种基本数据类型
2.8. 系统规则
- 官方文档
- 作用域
全局的,兜底的。
参数 | 说明 | 默认值 |
---|---|---|
LOAD | load1 触发值,用于触发自适应控制阶段 | -1 (不生效) |
RT | 所有入口流量的平均响应时间 | 同上 |
线程数 | 入口流量的最大并发数 | 同上 |
入口 QPS | 所有入口资源的 QPS | 同上 |
CPU 使用率 | 当前系统的 CPU 使用率(0.0-1.0) | 同上 |
2.9. 授权控制规则
- 官方文档
*如何生效
和【流控规则】-【针对来源】的使用很像,也需要实现RequestOriginParser接口。
2.10. 集群规则
- 开源版没有生效,没有实现。
- 云上版本ASAS 付费版提供开箱即用。
3. 安装控制台
3.1. 默认端口8080
3.2. 下载jar包
- 点击官网的github链接,找到自己版本,点击Downloads,拉到底找Jar
https://github.com/alibaba/Sentinel/releases/tag/1.8.6
3.3. 运行jar包
官网--文档--Sentinel控制台有“启动命令”
// 用户、密码都是 sentinel
// -Dcsp.sentinel.dashboard.server=localhost:8587 用于指定访问ip和端口
// Dproject.name=sentinel-dashboard 是左边菜单栏名称
java -Dserver.port=8587 -Dcsp.sentinel.dashboard.server=localhost:8587 -Dproject.name=sentinel-dashboard -jar sentinel的jar文件
4. 控制台
4.1. 菜单说明
4.2. 规则持久化问题
默认流控规则是存于内存,重启即清除
4.2.1. 三种规则推送模式
4.2.1.1. 原始模式
- 默认模式
浏览器控制台通过api将规则推送给订单服务,更新到内存中。 - 优点
简单,无依赖。 - 缺点
sentinel的jar包重启会消失,生产不适合。 - 改造方式
扩展数据源( WritableDataSource ),参考源码:com.alibaba.csp.sentinel.command.handler.ModifyRulesCommandHandler#handle();
4.2.1.2. 拉模式
- 实现
订单微服务主动向某个 规则管理中心,定时3s轮询拉取规则,这个规则中心可以是RDBMS,文件等。 - 优点
简单,无依赖,规则又持久化了。 - 缺点
不保证一致性,实时性不保证,拉取过于频繁有性能问题。 - 改造方式
扩展写数据源( WritableDataSource )
官方方案:基于文件实现拉取,demo : sentinel-demo/sentinel-demo-dynamic-file-rule
基于Nacos的拉模式,实现写数据源,当浏览器控制台推送规则到内存后,就将规则发布到Nacos配置中心,可参考com.alibaba.nacos.client.config.NacosConfigService
4.2.1.3. 推模式
- 实现
规则管理中心(浏览器控制台)统一推送,订单服务通过注册监听器,接受最新规则,使用Nacos、Zookeeper等配置中心。 - 优点
更好的实时性和一致性,规则又持久化了。 - 缺点
需要引入第三方依赖 - 改造方式
扩展读数据源(ReadableDataSource)
官方实现方案:Nacos配置中心控制台推送--官方demo: sentinel-demo-nacos-datasource
4.2.1.4. 官方实现
此方案无法实现,修改sentinel浏览器控制台,更新到nacos持久化
- 1:引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
-
2:yml添加从Nacos读取流控规则配置
-
rule-type的值
详情见:com.alibaba.cloud.sentinel.datasource.RuleType -
3:nacos配置中心配置流控规则
4.2.1.4.1. 如何解决浏览器控制台修改规则,同步到Nacos
- 方案1
【不建议】改源码(可能不同版本,需要改的地方不一样),重新打一个Jar包,修改规则时同时推送给Nacos配置中心。 - 方案2
自己在微服务端扩展写数据源(WritableDataSource),将规则保存到Nacos配置中心。
思路:推拉结合,使用官方提供的读数据源扩展,自己实现Nacos写数据源。
代码:gitee,v2.4.2版本。
5. 微服务如何整合
5.1. pom加入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
5.2. 如何让资源(方法)受保护
- mvc接口自动埋点,自动支持
- 非mvc接口需要加@SentinelResource,官方说需要配合 Spring AOP 或者 AspectJ 一起使用。
- 微服务的Controller的所有uri会自动被扫描
通过在控制台,动态配置流控、熔断规则
5.3. application.yml添加 sentinel 控制台地址
spring:
application:
name: tlmall-order
cloud:
sentinel:
transport:
# 添加sentinel的控制台地址
# 控制台jar包 启动命令行参数 -Dcsp.sentinel.dashboard.server=的值
dashboard: localhost:8587
6. 常见问题
6.1. 微服务限流没生效
- 如果Sentinel部署在公网,业务微服务在本地,本地需要内网穿透暴露一个公网可访问地址。
7. 服务雪崩问题
7.1. 解决方案
7.1.1. 超时机制
- openFeign 配置连接和读取超时时间
7.1.2. 服务限流
- 限制QPS
7.1.3. 资源隔离
- 进程隔离,线程隔离,信号量隔离
7.1.4. 服务熔断降级
8. 注解
8.1. @SentinelResource
- 解析SentinelResource注解逻辑在:SentinelResourceAspect
9. 单独使用
- 非微服务项目,未引alibaba cloud
9.1. 引入依赖
- 2个依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.6</version>
</dependency>
AOP依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.6</version>
</dependency>
与控制台通信依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.6</version>
</dependency>
9.2. 注册bean
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
9.3. 方法上加@SentinelResource
// ---------------- 方法在本类的用法 ----------------
// handleException和fallbackException方法参数需要和hello2的保持一致,最后再加上BlockException或Throwable
// blockHandler = "handleException" 这种是当该方法抛出BlockException执行handleException方法
// fallback = "fallbackException" 代表:该方法抛出Throwable 执行fallbackException
// blockHandler满足优先执行
@SentinelResource(value = RESOURCE_NAME, blockHandler = "handleException",
fallback = "fallbackException")
// ---------------- 方法在其它类的用法 ----------------
// 该方法触发了BlockException异常,会调用ExceptionUtil的handleException()方法。
// @SentinelResource(value = RESOURCE_NAME,
// blockHandler = "handleException",blockHandlerClass = ExceptionUtil.class,
// fallback = "fallbackException",fallbackClass = ExceptionUtil.class)
@RequestMapping("/hello2")
public String hello2() {
int i = 1 / 0;
return "helloworld ";
}
// Block 异常处理函数,参数最后多一个 BlockException,其余与原方法hello2一致.
public String handleException(BlockException ex){
return "被流控了";
}
// Fallback 异常处理函数,参数与原方法hello2一致或加一个 Throwable 类型的参数.
public String fallbackException(Throwable t){
return "被异常降级了";
}
}
10. 在微服务中使用
10.1. 引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
10.2. 配置哪些方法需要保护
- springMVC Controller层自动识别
10.3. 配置yml
feign:
sentinel:
enabled: true #开启Sentinel 对 Feign 的支持
spring:
cloud:
nacos:
discovery:
server-addr: tlmall-nacos-server:8848
sentinel:
transport:
# 添加sentinel的控制台地址
dashboard: tlmall-sentinel-dashboard:8888
# 指定应用与Sentinel控制台交互的端口,应用会起一个HttpServer占用该端口
port: 8719
10.4. 和openFeign整合
10.4.1. 整合源码
- com.alibaba.cloud.sentinel.feign.SentinelInvocationHandler
10.4.2. @FeignClient
@FeignClient(value = "tlmall-order-sentinel-demo",path = "/order",fallback = FallbackOrderFeignService.class)
public interface OrderFeignService {
/**
* 根据用户id查询订单信息
* @param userId
* @return
*/
@GetMapping("/getOrder")
Result<?> getOrder(@RequestParam("userId") String userId);
}
10.4.2.1. fallback使用示例
@Component //必须交给spring 管理
public class FallbackOrderFeignService implements OrderFeignService {
@Override
public Result getOrder(String userId) {
return Result.failed("=======服务降级了========");
}
@Override
public Result<?> post1(OrderDTO orderDTO) {
return Result.failed("=======服务降级了========");
}
@Override
public Result<?> post2(OrderDTO orderDTO, String token) {
return Result.failed("=======服务降级了========");
}
@Override
public Result<?> post3(OrderDTO orderDTO, String userId) {
return Result.failed("=======服务降级了========");
}
}
10.4.2.2. fallbackFactory 使用示例
@FeignClient(value = "tlmall-order-sentinel-demo",path = "/order",fallback = FallbackOrderFeignServiceFactory.class)
public interface OrderFeignService {
/**
* 根据用户id查询订单信息
* @param userId
* @return
*/
@GetMapping("/getOrder")
Result<?> getOrder(@RequestParam("userId") String userId);
}
@Component
public class FallbackOrderFeignServiceFactory implements FallbackFactory<OrderFeignService> {
@Override
public OrderFeignService create(Throwable throwable) {
return new OrderFeignService() {
@Override
public Result getOrder(String userId) {
return Result.failed("=======服务降级了========");
}
@Override
public Result<?> post1(OrderDTO orderDTO) {
return Result.failed("=======服务降级了========");
}
@Override
public Result<?> post2(OrderDTO orderDTO, String token) {
return Result.failed("=======服务降级了========");
}
@Override
public Result<?> post3(OrderDTO orderDTO, String userId) {
return Result.failed("=======服务降级了========");
}
};
}
}
11. restTemplete整合Sentinel
11.1. 应用场景
第三方提供接口(微信支付的查询,飞书扫码登录接口),没法用openFeign
11.2. 如何使用
- 1: 引入依赖
- 2:yml添加sentinel控制台配置信息
spring:
cloud:
sentinel:
transport:
# 添加sentinel的控制台地址
dashboard: tlmall-sentinel-dashboard:8888
# 指定应用与Sentinel控制台交互的端口,应用会起一个HttpServer占用该端口
port: 8719
# 开启resttemplate的sentinel流控切面支持【引入依赖后,默认为true】
resttemplate:
sentinel:
enabled:true
- 3:RestTemplate添加@SentinelRestTemplate
@Configuration
public class RestConfig {
/**
* handleBlockException和handleFallback的参数是固定的
*/
@Bean
@LoadBalanced
@SentinelRestTemplate(
blockHandler = "handleBlockException",blockHandlerClass = ExceptionUtil.class,
fallback = "handleFallback",fallbackClass = ExceptionUtil.class
)
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
- 4: blockHandler和fallback函数的固定参数写法
必须为static方法
public class ExceptionUtil {
public static SentinelClientHttpResponse handleBlockException(HttpRequest request,
byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
Result result = Result.failed("===被限流啦===");
try {
return new SentinelClientHttpResponse(new ObjectMapper().writeValueAsString(result));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
public static SentinelClientHttpResponse handleFallback(HttpRequest request,
byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
Result result = Result.failed("===被异常降级啦===");
try {
return new SentinelClientHttpResponse(new ObjectMapper().writeValueAsString(result));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
12. 微服务端源码
12.1. 实现原理
- 基于AOP
SentinelResourceAspect 负责处理
12.2. 处理顺序
-
基于spi加载
-
用责任链依次处理
12.3. 流控
12.3.1. 流控效果
- 快速失败
算法:滑动时间窗口
com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController - Warm Up 预热时长
算法:令牌桶算法
WarmUpController - 排队等待
算法:漏桶算法
RateLimiterController
12.4. 熔断
-
处理类
com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot -
熔断开关控制类
com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.ExceptionCircuitBreaker
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码