【SpringCloud合集-04】Sentinel 流量控制与熔断降级 学习笔记

📅 2026/7/13 2:45:42
【SpringCloud合集-04】Sentinel 流量控制与熔断降级 学习笔记
目录一、核心定位与整体架构1.1 什么是 Sentinel1.2 Sentinel 与 Hystrix 核心对比1.3 核心架构二、Spring Cloud Alibaba 整合实战2.1 基础整合三步法第一步引入依赖第二步配置控制台地址第三步启动类与基础使用2.2 自定义资源与降级处理2.3 流量控制实战三种流控效果2.4 熔断降级实战三种熔断策略2.5 OpenFeign 整合降级实战第一步开启 Feign 支持第二步定义降级实现类第三步Feign 接口指定降级类三、核心执行流程与源码解析3.1 完整调用链路图3.2 核心入口 SphU.entry () 源码解析3.3 核心插槽职责详解3.4 滑动窗口统计原理核心设计3.5 熔断状态机原理四、高级特性与生产配置4.1 热点参数限流4.2 系统自适应保护4.3 规则持久化三种持久化模式生产推荐Nacos 推模式整合4.4 授权规则与黑白名单五、实战踩坑与最佳实践5.1 高频踩坑点5.2 最佳实践六、面试速记总结基于 Spring Cloud Alibaba 2.2.x Sentinel 1.8.x 源码学习一、核心定位与整体架构1.1 什么是 SentinelSentinel 是阿里巴巴开源的流量控制与熔断降级组件面向分布式服务架构以流量为切入点从流量控制、熔断降级、系统自适应保护等多个维度保障服务的稳定性。它是 Spring Cloud Alibaba 生态的核心容错组件全面替代了已停止维护的 Netflix Hystrix。核心定位在高并发、高可用的分布式系统中当系统出现流量突增、下游服务故障、资源不足等情况时通过限流、降级、熔断等手段保证当前服务不被打垮避免故障在链路中逐级扩散防止雪崩效应。三大核心能力流量控制控制接口的请求速率QPS / 线程数将随机流量调整为平滑形状保护系统不被突发流量冲垮熔断降级当下游服务出现慢调用、高异常时暂时切断对该服务的调用快速失败避免拖垮当前服务系统自适应保护从系统整体维度出发结合负载、CPU、响应时间等指标自动调整入口流量让系统运行在最大吞吐量的安全水位1.2 Sentinel 与 Hystrix 核心对比对比维度SentinelNetflix Hystrix维护状态阿里开源社区活跃持续迭代Netflix 官方已停止维护进入休眠期隔离策略信号量隔离默认、支持线程池隔离线程池隔离默认、信号量隔离流量控制支持 QPS、线程数、热点、系统保护等多种限流规则无原生限流能力仅做熔断降级熔断策略慢调用比例、异常比例、异常数 三种策略仅异常比例一种熔断策略滑动窗口高性能滑动窗口LeapArray毫秒级精度滑动窗口实现较重精度较低控制台提供可视化控制台支持动态规则配置、监控、链路查询仅提供基础监控面板配置需代码硬编码扩展性插槽责任链设计扩展灵活扩展性一般考点Hystrix 核心思想是「线程池隔离」通过不同服务用不同线程池实现故障隔离但线程切换开销大Sentinel 主打「轻量信号量隔离 全方位流量控制」性能损耗更低功能更全面是目前国内微服务架构的主流选型。1.3 核心架构核心设计思想资源Sentinel 的核心概念一切需要保护的东西都可以定义为资源接口、方法、代码块规则围绕资源配置的管控规则包括流控规则、降级规则、系统规则等插槽责任链所有校验逻辑通过 ProcessorSlot 插槽串联成责任链按顺序执行新增功能只需加新插槽扩展性极强滑动窗口底层用高性能滑动窗口统计实时指标所有规则判断都基于统计数据二、Spring Cloud Alibaba 整合实战2.1 基础整合三步法第一步引入依赖dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-sentinel/artifactId /dependency第二步配置控制台地址spring: cloud: sentinel: transport: dashboard: 127.0.0.1:8080 # Sentinel控制台地址 port: 8719 # 客户端与控制台通信端口默认8719冲突自动递增 eager: true # 开启饥饿加载项目启动立即初始化Sentinel无需等第一次请求 web-context-unify: false # 关闭上下文统一按URL区分不同资源链路第三步启动类与基础使用Sentinel 对 Spring MVC 接口做了自动埋点所有 Controller 接口默认都是受保护的资源资源名就是请求路径。无需额外代码启动后即可在控制台配置流控规则。2.2 自定义资源与降级处理通过SentinelResource注解可以自定义资源名并指定限流、降级的兜底处理方法粒度更细。Service public class OrderService { /** * SentinelResource 标记受保护的资源 * value 资源名控制台按此名称配置规则 * blockHandler 限流/系统保护触发时的兜底方法 * fallback 业务异常/熔断触发时的兜底方法 */ SentinelResource( value createOrder, blockHandler createOrderBlockHandler, fallback createOrderFallback ) public String createOrder(Long userId, Long goodsId) { // 业务逻辑创建订单 return 订单创建成功; } /** * 限流兜底方法触发流控/熔断/系统保护时调用 * 方法签名必须和原方法一致最后多一个BlockException参数 */ public String createOrderBlockHandler(Long userId, Long goodsId, BlockException ex) { return 系统繁忙请稍后再试; } /** * 业务异常兜底方法原方法抛出业务异常时调用 * 方法签名必须和原方法一致最后多一个Throwable参数 */ public String createOrderFallback(Long userId, Long goodsId, Throwable e) { return 订单创建失败服务降级; } }关键区别说明blockHandler处理 Sentinel 规则校验失败的异常限流、熔断、系统保护对应BlockExceptionfallback处理业务代码本身抛出的异常也包含熔断后的异常对应Throwable两者同时配置时触发限流走 blockHandler触发业务异常走 fallback职责分离2.3 流量控制实战流量控制是 Sentinel 最核心的能力通过配置规则限制资源的访问速率。核心规则参数参数说明资源名受保护的资源标识对应 SentinelResource 的 value阈值类型QPS 模式每秒请求数线程数模式并发线程数单机阈值限流的临界值超过则触发限流流控模式直接限流、关联限流、链路限流流控效果快速失败、Warm Up 预热、排队等待三种流控效果快速失败默认模式超过阈值直接抛出异常适合对延迟不敏感、拒绝服务优先的场景Warm Up 预热冷启动模式阈值从低到高缓慢上升到设定值适合秒杀等流量突增场景避免瞬间把系统压垮排队等待匀速通过模式请求排队依次通过超过超时时间则失败适合消息队列、任务处理等场景把突刺流量整形为平滑流量2.4 熔断降级实战熔断降级用于保护下游依赖当下游服务出现故障时暂时切断调用快速失败避免拖垮当前服务。三种熔断策略慢调用比例当单位时间内慢调用响应时间超过设定阈值占比达到阈值触发熔断适合防范下游慢响应拖垮本地线程异常比例当单位时间内异常调用占比达到阈值触发熔断适合下游大面积报错的场景异常数当单位时间内异常次数达到阈值触发熔断适合低流量场景的异常判断熔断后会进入熔断打开状态所有请求直接降级经过设定的熔断时长后进入半开状态放行一个探测请求如果成功则关闭熔断恢复正常如果失败则继续保持熔断。2.5 OpenFeign 整合降级实战Sentinel 原生适配 OpenFeign开启后可以对 Feign 接口做熔断降级。还有针对RestTemplate的配置使拥有熔断降级的功能因为用的少就不加入了后续需要使用看下相关文档就可也容易配置。第一步开启 Feign 支持feign: sentinel: enabled: true # 开启Sentinel对Feign的支持第二步定义降级实现类Component public class UserFeignClientFallback implements UserFeignClient { Override public User getUserById(Long userId) { // 熔断/限流时的降级逻辑 User user new User(); user.setId(userId); user.setNickname(用户服务暂不可用); return user; } }第三步Feign 接口指定降级类FeignClient(value user-service, fallback UserFeignClientFallback.class) public interface UserFeignClient { GetMapping(/user/{id}) User getUserById(PathVariable(id) Long userId); }触发逻辑当 user-service 调用超时、异常、达到熔断阈值时自动走降级实现类返回兜底数据不会抛出异常保证主链路可用。三、核心执行流程与源码解析3.1 完整调用链路图3.2 核心入口 SphU.entry () 源码解析所有 Sentinel 限流逻辑的触发入口都是SphU.entry()注解和自动埋点最终都会调用这个方法。// com.alibaba.csp.sentinel.SphU public static Entry entry(String name) throws BlockException { // 委托给CtSph执行 return Env.sph.entry(name, EntryType.OUT, 1, OBJECTS0); }核心实现类CtSph的执行逻辑Override public Entry entry(String name, EntryType type, int count, Object... args) throws BlockException { // 1. 获取资源对应的插槽责任链 ProcessorSlotObject chain lookProcessChain(resourceWrapper); if (chain null) { return new CtEntry(resourceWrapper, null, context); } Entry e new CtEntry(resourceWrapper, chain, context); try { // 2. 依次执行责任链所有插槽的entry方法 chain.entry(context, resourceWrapper, null, count, prioritized, args); } catch (BlockException e1) { // 3. 规则校验不通过退出并抛出异常 e.exit(count, args); throw e1; } return e; }设计解析采用责任链模式所有校验逻辑解耦到独立的 Slot 中按顺序执行新增功能只需新增 Slot 插入链中完全符合开闭原则每个资源对应一条独立的责任链第一次访问时构建后续复用缓存到内存中业务代码执行完成后必须调用entry.exit()更新统计数据否则会导致统计异常3.3 核心插槽职责详解按执行顺序排列每个插槽各司其职插槽职责NodeSelectorSlot构建调用链路树维护资源的调用路径区分不同上下文的同资源调用ClusterBuilderSlot构建集群维度的统计节点关联资源的全局统计数据StatisticSlot核心统计槽记录请求通过、阻塞、异常、响应时间等实时指标是所有规则判断的数据基础FlowSlot流量控制槽根据流控规则校验当前请求是否通过超限则抛出异常DegradeSlot熔断降级槽根据熔断规则判断服务状态熔断状态下直接拒绝SystemSlot系统保护槽从系统整体维度校验超过系统阈值则拒绝入口流量源码考点插槽的顺序是固定的统计槽在规则槽前面保证先记录数据再做判断退出时按逆序执行 exit 方法更新统计结果。3.4 滑动窗口统计原理所有限流、熔断规则的判断都依赖实时统计数据Sentinel 采用高性能滑动窗口LeapArray实现毫秒级的指标统计。核心设计将时间划分为多个等长的窗口bucket每个窗口记录该时间段内的指标通过数、异常数、总耗时等窗口随时间滑动过期的窗口会被重置复用避免频繁创建对象采用数组存储窗口环形数组结构通过时间戳取模定位当前窗口时间复杂度 O (1)// LeapArray核心结构 public abstract class LeapArrayT { protected int windowLengthInMs; // 单个窗口时长毫秒 protected int sampleCount; // 窗口总数 // 因为时间无限但内存有限所以数据存满后新数据会覆盖最旧的数据。 protected final AtomicReferenceArrayWindowWrapT array; // 环形窗口数组 // 根据时间戳定位当前窗口 protected WindowWrapT currentWindow(long timeMillis) { // 计算当前时间对应的窗口索引 int idx calculateWindowIdx(timeMillis); // 计算窗口开始时间 long windowStart calculateWindowStart(timeMillis); // CAS方式更新窗口过期则重置 while (true) { WindowWrapT old array.get(idx); if (old null) { // 创建新窗口 } else if (windowStart old.windowStart()) { return old; } else if (windowStart old.windowStart()) { // 窗口过期重置复用 if (old.updateStart(windowStart)) { resetWindow(old); return old; } } } } }性能优势无锁设计通过 CAS 更新窗口高并发下性能优异窗口复用内存占用固定不会随时间增长统计精度高默认 1 秒划分为 2 个窗口精度 500ms可自定义调整3.5 熔断状态机原理Sentinel 熔断采用经典的三态状态机设计比 Hystrix 更精细。关闭状态Closed正常状态所有请求正常通过持续统计慢调用 / 异常比例打开状态Open达到熔断阈值后触发所有请求直接快速失败不调用下游半开状态Half-Open熔断持续设定时长后进入半开状态放行一个探测请求探测请求成功熔断关闭恢复正常探测请求失败重新进入打开状态重新计时源码中由CircuitBreaker接口定义默认实现ResponseTimeCircuitBreaker、ExceptionCircuitBreaker核心判断逻辑在tryPass方法中Override public boolean tryPass() { if (currentState.get() State.CLOSED) { return true; } if (currentState.get() State.OPEN) { // 判断熔断时长是否到期到期则转为半开 if (retireTime() TimeUtil.currentTimeMillis()) { if (currentState.compareAndSet(State.OPEN, State.HALF_OPEN)) { return true; // 放行一个探测请求 } } return false; } // 半开状态下只放行第一个请求后续都拒绝 return false; }四、高级特性与生产配置4.1 热点参数限流普通限流是针对整个资源的整体限流热点参数限流可以针对具体参数值做更细粒度的控制比如秒杀场景下限制单个商品 ID 的访问频率。使用方式SentinelResource(getGoodsDetail) HotResource(paramIdx 0) // 标记第0个参数为热点参数 public Goods getGoodsDetail(Long goodsId) { return goodsMapper.selectById(goodsId); }控制台可以配置针对 goodsId 参数的限流阈值比如单个商品 ID 每秒最多访问 100 次防止热点商品打垮系统。注意仅支持基本类型和 String 类型参数不支持复杂对象底层用 LRU 缓存统计热点参数性能优异。4.2 系统自适应保护从系统整体维度进行流量控制防止入口流量过大导致系统崩溃支持五个维度的阈值Load 自适应系统负载超过阈值时限流仅 Linux 生效CPU 使用率CPU 使用率超过阈值时限流平均响应时间所有入口流量的平均响应时间超过阈值时限流并发线程数所有入口流量的并发线程数超过阈值时限流入口 QPS所有入口流量的总 QPS 超过阈值时限流核心价值不用逐个接口配置限流从系统水位层面做兜底保护适合做整体的安全防线。4.3 规则持久化默认情况下控制台配置的规则只存在客户端内存中应用重启就会丢失生产环境必须做规则持久化。三种持久化模式模式原理优点缺点原始模式控制台推送规则到客户端内存简单开箱即用重启丢失不能持久化拉模式客户端定时从文件 / Nacos 拉取规则简单依赖少实时性差有延迟推模式控制台将规则推送到 Nacos客户端监听 Nacos 实时更新实时性高持久化可靠生产推荐需要改造控制台配置稍复杂生产推荐Nacos 推模式整合1.引入依赖dependency groupIdcom.alibaba.csp/groupId artifactIdsentinel-datasource-nacos/artifactId /dependency2.配置数据源spring: cloud: sentinel: datasource: flow: nacos: server-addr: 127.0.0.1:8848 dataId: sentinel-flow-rules groupId: DEFAULT_GROUP rule-type: flow # 流控规则规则存储在 Nacos 中修改 Nacos 配置即可实时更新应用重启也不会丢失是生产环境的好方案。4.4 授权规则与黑白名单通过RequestOriginParser解析调用方来源配置黑白名单控制哪些调用方可以访问资源适合网关层、内部服务间的权限控制。Component public class CustomOriginParser implements RequestOriginParser { Override public String parseOrigin(HttpServletRequest request) { // 从请求头中获取调用方标识 return request.getHeader(service-name); } }控制台配置授权规则指定白名单或黑名单即可。五、实战踩坑与最佳实践5.1 高频踩坑点SentinelResource 降级方法不生效原因降级方法必须和原方法在同一个类中不加xxxClass属性时且方法签名必须完全一致最后多一个异常参数方法必须是 public且不能是静态方法。 解决严格匹配方法签名异常类型对应准确blockHandler 对应 BlockExceptionfallback 对应 Throwable业务异常也兜底。异步调用统计异常原因异步线程中执行业务代码Sentinel 的 entry 在主线程就退出了统计不到异步执行的结果和异常。SentinelResource是基于线程上下文ContextUtil.enter()绑定的。主线程调用entry后立即返回异步线程执行时主线程的Context已经退出了。 解决手动在异步线程内调用 SphU.entry () 和 exit ()或者使用支持异步的注解版本。在异步任务中必须使用SphU.asyncEntry(resourceName)获得AsyncEntry并在异步回调的finally中调用entry.exit()这样才能正确统计异步执行的 RT 和异常。Feign 降级不生效原因没有开启feign.sentinel.enabledtrue降级类没有加 Component 注解降级类没有正确实现 Feign 接口。 解决逐项检查配置确保降级类被 Spring 容器管理。规则配置后不生效原因资源名不匹配比如注解自定义了资源名但控制台按 URL 配置了规则或者客户端没有正确连接控制台。 解决核对资源名查看控制台簇点链路是否出现对应资源确认客户端心跳正常。流控阈值不准原因滑动窗口有精度误差窗口切换瞬间可能有短暂超阈值或者并发极高时CAS 统计有微小误差。 解决阈值设置留一定余量不要卡着极限配置这是所有滑动窗口限流的共性问题属于正常现象。5.2 最佳实践分层限流网关层做总入口限流服务层做接口级限流核心方法做方法级限流多层防护降级兜底所有核心外部依赖都配置熔断降级兜底逻辑要轻量不能再调用外部依赖规则持久化生产环境必须使用 Nacos 等持久化数据源禁止依赖内存规则监控告警对接监控系统监控限流次数、熔断次数、异常率设置告警阈值参数校验限流是最后一道防线前置要做好参数校验、缓存、降级不能单纯依赖限流压测验证上线前通过压测验证限流阈值是否准确降级逻辑是否正常避免线上出问题六、面试速记总结核心定位Sentinel 是阿里开源的流量控制与熔断降级组件替代 Hystrix以流量为切入点保障分布式系统稳定性。三大核心能力流量控制QPS / 线程数、三种流控效果、熔断降级三种策略、三态状态机、系统自适应保护。核心设计插槽责任链模式按顺序执行节点构建、统计、限流、熔断、系统保护校验扩展性极强。统计原理基于高性能滑动窗口 LeapArray环形数组 CAS 无锁更新毫秒级精度高并发性能优异。熔断原理关闭→打开→半开三态状态机熔断时长到期后放行探测请求成功则恢复失败则继续熔断。生产配置控制台做规则管理Nacos 做规则持久化推模式分层限流 熔断降级 系统保护三道防线。与 Hystrix 区别Sentinel 轻量信号量隔离限流功能完善控制台强大社区活跃Hystrix 线程池隔离仅熔断已停止维护。