
1. Sentinel 到底在解决什么问题先说个真实的场景。你负责的服务平时每秒就几百次调用结果某天运营搞了个活动流量瞬间冲到每秒几千次。数据库连接池被打满接口响应时间从 50ms 涨到 5 秒紧接着依赖的下游服务开始超时超时的请求又堆积在 Tomcat 线程池里把线程也耗尽。这时候就算你把接口限流到每秒 1000 次也已经来不及了——因为故障已经蔓延开了。业内把这种现象叫雪崩效应。一个服务的故障像多米诺骨牌一样顺着调用链一路传导最后把整个系统拖垮。Sentinel 就是为了解决这类问题而生的它是阿里巴巴开源的流量控制组件核心能力说白了就三个限流、熔断降级、系统负载保护。对比一下同类工具Hystrix 大家应该也听说过但它已经进入维护模式了而且它的熔断设计比较重线程池隔离的开销不小。Sentinel 的轻量级设计更适合现代微服务架构直接以 Java 类库的形式嵌入应用不依赖额外的独立服务控制台是可选的资源粒度可以精细到任意方法、任意接口甚至任意代码块。更重要的是它的规则配置支持动态推送改规则不用重启应用这在排障和生产运维的时候简直是救命的功能。这篇文章我们就从零开始把 Sentinel 的核心概念、接入步骤、规则配置和常见坑过一遍。不管你是刚接触微服务的新手还是已经在生产环境里被流量冲击折磨过的老手照着这篇文章的思路走一遍 Sentinel 的基本用法就能拿下了。2. 五分钟快速接入 Sentinel2.1 环境准备与依赖引入接入 Sentinel 的前提是你的项目是 Spring Boot / Spring Cloud 体系JDK 8 以上。这里我用最常规的 Spring Boot 2.x Maven 项目来演示。引入依赖的时候推荐使用 Spring Cloud Alibaba 的 BOM 统一管理版本避免自己手动匹配带来的版本冲突。dependencyManagement dependencies dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-alibaba-dependencies/artifactId version2021.0.5.0/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-sentinel/artifactId /dependency如果用的是 Spring Cloud 2021 之后的版本还需要额外引入spring-cloud-starter-bootstrap依赖因为新的版本默认不再启用 bootstrap 配置文件而 Sentinel 的某些配置需要从 bootstrap.yml 里读取。这个坑我踩过后面在问题排查部分会细说。2.2 启动控制台Sentinel 控制台是一个独立的 Web 应用用来可视化地查看实时监控、配置规则。从 GitHub 的 Release 页面下载sentinel-dashboard-1.8.x.jar直接启动java -Dserver.port8080 -jar sentinel-dashboard-1.8.6.jar启动成功后浏览器访问http://localhost:8080默认账号密码都是sentinel。控制台本身不复杂左边是机器列表右边是实时监控和规则配置面板。这里有个新手容易困惑的点控制台默认只保存在内存里应用一重启控制台上配置的规则就全没了。这个话题后面专门讲持久化方案。2.3 配置文件中接入应用在 Spring Boot 的配置文件里加上控制台地址以及让自己服务能被控制台发现spring: application: name: order-service cloud: sentinel: transport: dashboard: localhost:8080 port: 8719port: 8719是应用与控制台通信的端口用于上报心跳和监控数据。如果这个端口被占用Sentinel 会自动尝试下一个端口实际生效的端口号会在启动日志里打出来。启动应用后在控制台的机器列表里就能看到对应的服务了。注意控制台只会显示有流量经过的接口。刚启动的应用如果没有请求进来控制台里看不到任何资源这是正常现象不是接入失败。第一次手动访问一下接口资源就会出现。3. 流量控制让服务按节奏工作3.1 阈值类型怎么选QPS 还是并发线程数Sentinel 的流控规则里阈值类型有两个选项QPS和并发线程数。这两个概念经常被搞混我举一个生活中的例子。想象一个银行柜台。QPS 相当于每分钟能接待多少位客户它衡量的是到达率。并发线程数相当于同时有几个窗口在办理业务它衡量的是正在处理的请求数。如果你的接口查询本地缓存每秒钟能处理一万次请求那就按 QPS 来限超过阈值直接拒绝保护下游数据库。如果你的接口涉及 RPC 调用或者复杂计算平均耗时 2 秒那单台机器能同时扛住的并发线程数就很有限。比如 Tomcat 默认 200 线程如果全部被慢请求占满其他接口也跟着遭殃。这时候按并发线程数来限流更合理比如限制并发线程数是 20多出来的请求直接排队或快速失败反而能保护调用链。实际配置时我的一般建议接口耗时小于 100ms 的走 QPS 限流耗时超过 500ms 的走并发线程数限流中间区间两者都行根据你的业务容忍度决定。3.2 三种流控模式直接、关联、链路直接模式最简单对指定资源限流。例如对/order/create接口设置 QPS100超过就拒绝。适用于核心接口的兜底保护。关联模式当两个接口共享同一个资源时比如下单接口和支付接口下单会导致数据库压力大进而影响支付。这时可以给支付接口设置规则阈值的统计对象关联到下单接口当下单接口 QPS 超过阈值时支付接口开始限流。本质是曲线保护——我不限制你下单价接口而是限流那个可能拖垮系统的坏小子。链路模式针对调用链路上的某一段做限流。比如一个接口被 A 和 B 两个服务调用A 是大流量入口B 是内部管理调用你只想限制 A 的流量不限制 B。这是更精细的治理手段需要配合SentinelResource注解来标记资源。链路模式最关键的一步在 Controller 里加上SentinelResource(value orderService.createOrder)然后在配置里开启链路收敛spring: cloud: sentinel: web-context-unify: false不关掉这个开关链路模式不生效。我之前排查过半天发现明明配了链路规则却一直走的是整个接口的流控原因就在这个默认值为true的配置项上。3.3 三种流控效果怎么处理超出的流量快速失败默认超出的请求直接抛异常客户端收到Blocked by Sentinel (flow limiting)。适合对接口实时性要求高、能容忍一定比例失败的业务。Warm Up阈值从某一个小值逐渐增长到预设值。典型的场景是秒杀系统刚开闸时流量是逐渐涨上来的如果瞬间放开全部阈值系统可能直接被冲垮。默认冷启动时间为 10 秒也就是 10 秒内阈值从阈值/3逐渐恢复到完整阈值。排队等待超出的请求不拒绝而是排队按固定的等待时间依次放行。这个模式用来削峰填谷适合处理瞬时突发流量。注意排队等待模式只对 QPS 阈值生效而且要设置超时时间比如 500ms 内排不上队就直接失败避免请求无限堆积。我记得有一次生产事故大促时某个活动页拉取商品详情的接口瞬间 QPS 冲到 8000服务直接雪崩。后来把这个接口改成 Warm Up 模式冷启动时间设成 20 秒阈值从 1000 逐渐加到 5000系统稳稳扛住了整场活动。这个经验后面又复制到了好几个接口上。4. 熔断降级给服务一个喘息的机会4.1 慢调用比例熔断熔断降级的核心思想对调用失败的比率设置一个阈值一旦超过阈值就打开熔断开关后续请求快速失败不去调用那个已经故障的下游服务给下游时间恢复。配置维度有三个最大 RT响应时间、比例阈值、熔断时长以及最小请求数量。比如配置最大RT200ms、比例阈值0.3、熔断时长5秒、最小请求数5。含义是在统计窗口内最少有 5 个请求其中有超过 30% 的请求 RT 大于 200ms那么熔断器打开持续 5 秒。5 秒过后进入半开状态放行少量探测请求如果还是慢继续熔断如果恢复了就自动闭合。这个配置里最容易忽略的是最小请求数。如果把最小请求数设成 1在低流量场景下哪怕只出现一次慢调用熔断也会触发这时候熔断反而成了常态。我一般建议最小请求数不低于 5线上流量稳定后可以设成 20。4.2 异常比例与异常数熔断慢调用比例针对的是响应时间另外两种策略针对的是业务异常。异常比例熔断统计周期内异常请求数占总请求数的比例超过阈值比如 30%触发熔断。适用于下游频繁报错的场景。异常数熔断统计周期内异常请求的数量超过 N 条直接熔断。适用于下游偶发异常的场景比如数据库偶尔抛连接超时只要积累到 20 条异常就熔断 5 秒而不是看比例。这两种策略有个共同的前提被熔断降级的异常必须是SentinelResource注解指定的blockHandler和fallback能捕获到的。我见过有人配好了熔断规则下游也发起异常了但熔断就是不触发。排查后发现他的异常类型不在 Sentinel 的统计范围内——Sentinel 默认只统计被SentinelResource标注的方法抛出的异常而且要通过fallback指定的兜底方法处理底层框架的调用链异常没有传到 Sentinel 上下文里。这块需要特别注意。4.3 熔断器状态流转Sentinel 的熔断器有三态关闭CLOSED、打开OPEN、半开HALF_OPEN。关闭正常状态下所有请求放行按规则统计指标。打开触发规则后所有请求直接拒绝不调用下游。半开熔断时间结束后进入半开状态放行少量探测请求。如果探测成功熔断器闭合如果失败重新打开。这里要强调一个容易被误会的点熔断时长是一个固定值但熔断状态是持续到熔断时间窗口结束后下一个请求进来时才去探测的。如果熔断期间没有请求进来那开关状态并不会自动变化。所以有些低流量系统熔断了半天都没恢复是因为没有新请求触发半开探测这是正常的从业务角度看反而是好事——没有流量就别打扰下游恢复。5. 规则持久化别让配置一夜回到解放前5.1 为什么控制台的规则不持久默认情况下你在 Sentinel 控制台上配置的规则只保存在控制台的 JVM 内存里并不会持久化到磁盘或数据库。有两个致命问题控制台重启规则全部丢失。应用重启规则全部丢失。因为 Sentinel 客户端启动后需要从控制台拉取规则如果控制台还没就绪或者规则在控制台里根本不在了那应用就是裸奔状态进入生产流量。所以生产环境必须做规则持久化。常见方案有三种方案实现方式优点缺点配置文件兜底在application.yml里通过spring.cloud.sentinel.rules配置规则简单随应用启动加载修改规则要重启应用Nacos 持久化Sentinel 客户端从 Nacos 读取规则控制台通过 Nacos 发布规则规则动态刷新无需重启需要额外部署 NacosApollo 持久化类似 Nacos适合已有 Apollo 配置中心的团队对接成本稍高对于绝大多数团队我推荐用 Nacos。它既能做配置中心又能做注册中心一套组件运维成本低。而且 Sentinel 支持把控制台的规则同步到 Nacos控制台上修改规则应用实时生效体验很好。5.2 控制台推送到 Nacos 的配置方式在项目的bootstrap.yml里增加 Nacos 数据源配置注意必须是 bootstrap.yml不是 application.ymlspring: cloud: sentinel: datasource: flow: nacos: server-addr: localhost:8848 dataId: order-service-flow-rules groupId: SENTINEL_GROUP rule-type: flow degrade: nacos: server-addr: localhost:8848 dataId: order-service-degrade-rules groupId: SENTINEL_GROUP rule-type: degrade这里的rule-type支持flow流控、degrade熔断、system系统规则、authority授权规则、param-flow热点参数五种类型。然后把 Nacos 的配置发布到对应的 dataId 下。流控规则的 JSON 格式大概是[ { resource: /order/create, limitApp: default, grade: 1, count: 100, strategy: 0, controlBehavior: 0, clusterMode: false } ]字段含义grade1表示按 QPS0表示并发线程数strategy0表示直接模式1关联模式2链路模式controlBehavior0表示快速失败1Warm Up2排队等待。这些字段和 Sentinel 控制台里看到的是完全对应的。注意这里有一个先到先得的原则。应用启动时是先去 Nacos 拉规则还是先连控制台取决于你配置的数据源是否就绪。如果 Nacos 地址不可用应用会启动失败吗不会。Sentinel 的懒加载机制会容忍拉取失败但规则缺失所以接入 Nacos 后务必在测试环境验证先把 Nacos 停了再看看应用能否正常启动。这个验证能提前暴露很多问题。6. 系统自适应保护与热点参数限流6.1 系统规则不盯单个接口看整体系统规则和前面的流控、熔断不同它不针对某一个具体的资源而是针对整个应用的系统维度。它有四个维度Load系统负载、CPU 使用率、平均 RT、入口 QPS。最常用的是 Load 规则当系统 1 分钟的平均 Load 超过某个阈值并且当前并发线程数超过系统容量的估计值就触发系统保护。这个机制的背后是系统容量估计算法Sentinel 会根据系统的 CPU 核数和并发线程数推算一个安全阈值让系统在过载时主动丢弃新请求保护已有的存量请求能够顺利完成。我曾经把一台 4 核 8G 的机器 Load 阈值设置为 4结果还没到高峰期就频繁触发保护后来把阈值改成 6反而更稳定了。因为系统 Load 高不一定是坏事关键是看系统是否还能承受并发。阈值设太低会误杀正常流量太高又起不到保护作用这个值最好通过压测定。6.2 热点参数限流精准打击热点参数限流的场景很典型一个查询接口同一个商品 ID 的访问量特别大但其他商品访问量很小。用 QPS 全局限流会误伤其他商品用热点参数限流就可以只对某个特定参数值限流。配置方式在接口方法上标记SentinelResource指定参数索引SentinelResource(value queryProduct, blockHandler queryProductBlockHandler) public Product queryProduct(RequestParam(productId) String productId) { // 业务逻辑 }然后在控制台添加热点规则参数索引0第一个参数单机阈值1000统计窗口时长60秒。更精细的做法是对特定的参数值设置例外项比如商品 ID10001的阈值单独设为100其他参数按默认阈值走。热点参数限流底层用的是一个滑动窗口计数器能精确到毫秒级别的突发流量控制对秒杀场景尤其有用。注意一个限制热参限流是针对基本类型参数的如果参数是对象你需要通过SentinelResource注解的entryType指定入口类型并配合申请ParamRequestWrapper来提取参数处理起来稍复杂新手期可以先避开。7. 生产环境实战中的几个常见问题与排查思路7.1 控制台机器列表看不到应用现象应用已经启动了也访问了接口但控制台机器列表是空的。排查步骤确认应用配置文件里有spring.cloud.sentinel.transport.dashboard配置。确认控制台地址能通curl localhost:8080试一下。看应用启动日志里有没有这句话Sentinel transport log has been initialized说明通信模块已经启动。看 8719 端口是否被占用了如果被占用看日志里实际启用的端口是多少控制台会用这个端口和应用通信。如果服务部署在 Docker 或 K8s 里要确保 8719 端口没有被防火墙拦掉至少要让控制台能访问到应用的 8719 端口。经验我见过一个 case服务在 K8s 里部署Pod 的网络模式是hostNetwork: false控制台在宿主机上结果一直看不到机器。后来调整成 CNI 的网络策略放通端口就解决了。容器化环境下网络策略是排查 Sentinel 的第一大坑。7.2 规则不生效why规则看似配置成功但流量超阈值后并没有被拦截。这个问题有几种可能资源名不匹配。你在控制台配置的资源名是/order/create但接口没有用SentinelResource标注Sentinel 自动埋点生成的资源名可能是GET:/order/create两者对不上规则自然不生效。解决方式手动用SentinelResource标注统一资源名。规则被覆盖。客户端启动时拉取了 Nacos 的规则之后控制台的修改没有同步到 Nacos而你改的又是在控制台直接改的。控制台的规则和应用拉取的规则是两个来源以 Nacos 为准。上下文关闭。链路模式下web-context-unify没有改为false导致链路统计不起作用只看整个接口的聚合流量。7.3 流量超过阈值但限流没有触发还有一种迷惑情况监控面板显示的 QPS 已经明显超过配置阈值但没有任何请求被拒绝。这种情况通常是阈值类型选错了。比如你配置的是并发线程数阈值但实际请求是快速返回的并发线程数始终上不去QPS 再高也不会触发。反过来也是你配置的是 QPS 阈值但流量是缓慢持续增长的没有瞬间冲到阈值也不会触发。另外Sentinel 的流量统计基于滑动窗口默认窗口长度是 1 秒但内部的格子是 500ms 一个。如果请求集中在某一个毫秒级时间点爆发可能一个窗口内没有超过阈值但下一秒窗口重叠的部分已经远超阈值这会导致限流效果有略微滞后。遇到极端敏感的限流需求可以把窗口调小但这属于调优范畴不是入门期的重点。7.4 熔断降级不生效的排障熔断不触发最常见的原因就是异常没有被 Sentinel 统计到。注意下面几个点只有被SentinelResource标注的方法抛出的异常才会计入熔断统计。普通的 Mapper 层异常、Service 内部异常如果没有被标注是不会被 Sentinel 自动感知的。fallback和blockHandler必须符合签名要求返回值和原方法一致参数要包含原方法的参数且blockHandler可以额外多一个BlockException参数。签名对不上即使配置了注解异常也会直接抛出而不进入熔断逻辑。如果你在SentinelResource里同时声明了fallback和blockHandler要清楚blockHandler处理的是被限流或熔断触发的场景fallback处理的是业务抛异常的场景。两者不要混用避免逻辑混乱。8. 最后分享一点个人体会Sentinel 入门最大的障碍不是概念多而是概念体系庞大但实际用得上的只有其中一部分。你不用一上来就学会所有规则类型先从流控规则的 QPS 限流开始把接口保护住再慢慢加熔断降级最后根据业务需要去研究热点参数和系统保护。个人在实践中很推荐一个配置组合核心接口用 QPS 限流快速失败 下游依赖用慢调用比例熔断RT 阈值 300ms比例 30%熔断 10 秒 整体用系统 Load 保护兜底。这套组合覆盖了流量入口、依赖故障、系统过载三个层面能在不牺牲用户体验的前提下让系统的稳定性上一个台阶。另外一个提升排障效率的小技巧在本地开发时把 Sentinel 的日志级别调成 DEBUG控制台打印的日志里会包含规则匹配的详细信息能直接看到某个请求命中了哪条规则、被以什么方式拒绝。线上就别这么干了DEBUG 日志的量和 QPS 成正比对性能影响不小。Sentinel 还有不少高级玩法比如集群流控、网关限流集成、与 OpenFeign 的熔断降级配合这些都是在入门后的下一个阶段值得研究的方向。先把这篇文章里的内容吃透把规则在测试环境里调通一遍再上生产。流量治理这件事最重要的不是工具多厉害而是你对系统瓶颈的判断够不够准。