news 2026/10/23 9:19:21

Sentinel限流实战:QPS与线程数模式选型及Nacos动态配置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Sentinel限流实战:QPS与线程数模式选型及Nacos动态配置

1. 先从一次线上事故说起:QPS 限流为什么会误伤慢请求

大概去年年中,我们有个核心接口因为下游依赖抖动,单次响应时间从 50ms 暴涨到 3s 左右。当时这套系统用的是 Sentinel QPS 限流,阈值设的 1000。表面上看,这个数字远高于平时的 100 QPS 均值,按理说不该触发限流。

结果恰恰是那个时刻,接口被限流得厉害,一堆请求直接拿到 Blocked 提示,业务方反馈"系统崩了"。

复盘的时候发现一个很扎心的事实:QPS 限流拦的不是"请求总量多",而是"瞬时流量超过阈值"。响应变慢之后,每条请求在 Tomcat 线程池里占着线程不释放,QPS 虽然可能没到 1000(因为处理不过来),但线程池被打满,新的请求进不来,Sentinel 统计的 QPS 自然就瞬间爆表。这就像一个餐厅只有 20 张桌子,每桌客人吃完要走 3 小时,哪怕你每小时只放 10 桌进来,门口排队的人也已经把大厅挤爆了。

那之后我开始认真研究 QPS 限流和线程数限流到底该怎么选。结论是:如果你的接口响应时间相对稳定,QPS 限流好用且性能开销小;如果你的接口会因外部依赖、慢 SQL、锁竞争等因素出现响应时间大幅波动,线程数限流才是更贴近系统真实承载能力的方案。

这篇文章我会把两种限流模式的控制原理、适用场景、性能差异和踩坑经验一次讲透,涉及到 Sentinel 整合 Nacos 动态配置的部分也会配上可以复制的样例,方便你直接落地到自己项目里。

2. 两种限流模式到底在"限"什么:QPS 控制速率,线程数控制并发占用

2.1 QPS 限流的核心逻辑:计数器 + 滑动窗口

QPS 限流是大多数人最先接触的限流方式。Sentinel 默认采用滑动窗口来统计每秒通过的请求数,你可以把它理解成"每秒最多放行多少个请求进入处理逻辑"。

核心判断逻辑用伪代码表示是这样的:

// 伪代码:QPS 限流判断逻辑 public boolean canPass() { long currentQps = slidingWindowCounter.getCurrentQps(); // 当前窗口内的 QPS 统计值 if (currentQps + 1 > rule.getCount()) { // rule.getCount() 即阈值 return false; // 拒绝 } return true; // 放行 }

这里有几个关键参数值得说清楚:

  • 阈值类型:QPS 模式下,count表示每秒允许通过的请求数量。比如设成 1000,含义是任意一秒内最多放行 1000 个请求。
  • 统计窗口:Sentinel 默认窗口长度是 1 秒,分成多个格子(默认 2 个格子,可通过windowIntervalMs和sampleCount调整),格子越多,统计越平滑,但内存开销也越大。
  • 流量效果:默认是"直接拒绝",也就是超出阈值直接返回 Blocked。也可以配成匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER),让请求以固定速率通过,适合削峰填谷的场景。

QPS 限流的核心假设是:每个请求消耗的系统资源大致相同。在这个假设成立的前提下,控制 QPS 就等于控制系统负载。

2.2 线程数限流的核心逻辑:信号量隔离

线程数限流走的是另一条路。它不关心你一秒进来多少个请求,只关心"当前有多少个请求正在同时执行"。Sentinel 在调用链路上埋了一个信号量(Semaphore),进入业务方法前acquire(),方法执行完(无论成功还是异常)后release()。

伪代码如下:

// 伪代码:线程数限流判断逻辑 public boolean canPass() { if (atomicCounter.getCurrentCount() + 1 > rule.getCount()) { return false; // 当前并发数已达阈值,拒绝 } atomicCounter.increment(); // 占用一个信号量 return true; }

注意一个细节:Sentinel 的线程数限流实现里,acquire()默认不支持排队等待,超了就立即返回失败。这和 QPS 限流里的匀速排队模式不一样,设计理念是"与其让请求排队占着线程,不如直接快速失败,让上游感知到压力"。

线程数限流的核心假设是:系统真正的瓶颈资源是线程。Tomcat 默认 200 个线程,每个线程同一时刻只能处理一个请求,所以"并发线程数"直接决定系统能同时处理多少请求。只要并发数被控制住,响应时间再长、慢请求再多,也不会无限挤压线程池。

2.3 两者的本质差异:速率控制 vs 资源占用控制

用一张表把两者的关键差异列清楚:

维度QPS 限流线程数限流
控制对象单位时间内的请求数量(速率)正在执行中的请求数量(并发)
核心统计量每秒通过的请求数当前持有的信号量计数
底层实现滑动窗口计数器信号量 + 原子计数
对慢请求的敏感度低(只数数量,不管耗时)高(请求耗时越长,占用越久)
响应时间波动时表现可能误判(线程积压但 QPS 不高)稳定(只约束并发上限)
内存开销中等(滑动窗口数组)低(一个计数器)
典型场景网关入口、短平快接口业务逻辑复杂、依赖下游的接口

一个特别容易混淆的点:QPS 限流并不能真正保护线程池。原因很简单,限流器只判断"这一秒能不能放进第 N 个请求",但每个请求会执行多久它完全不管。1000 QPS 的阈值,如果每个请求要执行 2 秒,那 Tomcat 的 200 个线程瞬间就被占满,后续请求就算通过了限量检查,也没线程可用,照样超时堆积。

而线程数限流直接约束"正在执行的请求数",比如设成 100,那么无论每秒进来多少请求,同时最多只有 100 个在跑,另外的会被快速拒绝。线程池始终有余量,系统不会死。

3. 什么场景该选 QPS,什么场景该选线程数:先判断你的瓶颈在哪

3.1 适合 QPS 限流的场景:接口耗时稳定、资源消耗均匀

我个人的判断标准是:先问自己,这个接口最底层依赖的资源是什么?如果控制住"请求进来速度"就能控制住资源消耗,那 QPS 限流就够用。

典型场景有三类:

  • 纯计算型接口:比如加解密服务、图片缩略图生成、本地缓存查询。这类接口不依赖外部系统,内存和 CPU 消耗基本恒定,执行时间波动很小。把 QPS 压到单个节点能承受的范围内,系统就很稳。
  • 网关层限流:在 Nginx、Spring Cloud Gateway、Sentinel Gateway 这一层做限流,目的不是保护某个业务服务,而是保护整个后端集群。这时用 QPS 限流最直观,语义清晰,业务方也容易理解。
  • 流量尖峰平滑:秒杀、抢购、活动预热场景,瞬间流量可能是平时的几十倍。如果你希望多余流量被"排成队"慢慢放行而不是直接拒绝,配合匀速排队模式用 QPS 限流很合适。

3.2 适合线程数限流的场景:响应时间波动大、有外部依赖

线程数限流的适用场景有一个共同特征:你无法准确预知每个请求会执行多久。

  • 下游 RPC 依赖多的接口:一个接口调用三四个下游服务,任何一个抖动都会导致整体耗时翻倍。此时 QPS 限流基本失灵——你以为限制住了请求量,但积压的请求还是会把线程池耗尽。
  • 数据库慢查询场景:慢 SQL 或者连接池打满时,所有走这条 SQL 的接口都会变慢。线程数限流可以保证"即使数据库快挂了,业务线程也不会积压太多",给其他接口留活路。
  • 第三方 API 调用对接:外部接口的响应时间你完全不可控,用线程数限流可以防止对方抖动拖垮你的整个应用。

3.3 一个很容易踩的误区:把 QPS 限流当作万能方案

我在很多项目里见过一种配置方式:所有接口统一加一个 QPS 限流,阈值拍脑袋填个 500 或 1000,之后就再也不管了。这种做法的隐患在于:

  • 接口耗时一旦上升,限流阈值立刻失真,限不住真正的问题。
  • 多个接口共享线程池时,一个慢接口的请求即使被限制在 QPS 阈值内,也可能会占完大部分线程,拖垮其他快接口。
  • 拍脑袋定的阈值没经过压测验证,要么太宽松等于没配,要么太严格天天误伤。

更好的做法是:上线前先压测拿到基线数据。用压测工具把接口压到 CPU 80% 左右,记录对应的 QPS 和并发线程数,然后按这个数据打折设置限流阈值。同时,对不同"危险程度"的接口分配不同的限流策略——依赖多的用线程数,纯计算的用 QPS。

3.4 两者混用也不冲突:先线程数兜底,再 QPS 控制入口速率

如果你拿不准选哪个,可以参考我目前比较推荐的组合方式:

  • 线程数限流作为第一道保险,设置一个接近线程池上限的安全值,比如 Tomcat 线程池 200,那就设 160。这样无论什么情况下,业务线程都不会被打满。
  • QPS 限流作为第二道控制,设置一个正常流量下的业务阈值,比如基线 QPS 的 80%。用来提前拦截突发流量,避免大量请求涌入后被线程数限流批量拒绝,造成频繁的上下文切换和资源浪费。

两道配合,比单选任意一种都稳。我最近在一个核心交易链路上就是这么配的,下游抖动时线程数限流先兜底,正常流量高峰时 QPS 限流提前削峰,效果明显好于之前只用 QPS 的方案。

4. 性能差异的底层原因:计数器、滑动窗口和信号量的开销对比

4.1 QPS 限流的开销来源:滑动窗口的数据结构

很多人以为 QPS 限流只是一个简单的AtomicLong.incrementAndGet(),其实不是。Sentinel 的 QPS 统计基于滑动窗口(Sliding Window),内部维护了一个环形数组,每个格子(WindowWrap)里保存着独立的LongAdder计数器。

为什么不用一个AtomicLong?因为 QPS 是"每秒"的统计量,你需要能区分出不同时间段的计数。滑动窗口的做法是:把时间轴切分成固定长度的小格,比如 500ms 一格,一个窗口保留最近 2 格的统计值。每次判断限流时,累加当前窗口所有格子的计数,和阈值比较。

这个结构的开销主要有三个:

  1. 每次请求的写入操作:需要定位当前时间属于哪个格子,然后调用LongAdder.add(1)。LongAdder在低并发下性能接近AtomicLong,高并发下通过分段 CAS 降低竞争,所以写入开销并不大。
  2. 定期格子过期和重置:时间窗口滑动时,旧的格子会被复用或重置,这个过程会有数组遍历的操作,但频率很低(每个格子周期一次)。
  3. 内存占用:每个格子包含一个LongAdder(内部有一个或多个 Cell),假设配置了 2 个格子、每个LongAdder内部 4 个 Cell,一次资源维度就要 8 个计数单元。规则多、资源维度多时,内存开销会线性增长。

实测下来,单机 5000 QPS 的情况下,QPS 限流的额外开销占整个请求处理时间的比例通常在 2% 以内,属于可接受的范围。

4.2 线程数限流的开销来源:信号量与原子计数

线程数限流的统计模型简单得多——只需要维护一个"当前并发数"的计数器。Sentinel 的实现里用的是AtomicInteger,配合compareAndSet做递增:

// Sentinel 线程数限流的核心计数器逻辑 private final AtomicInteger currentConcurrency = new AtomicInteger(0); public boolean tryAcquire(int count) { while (true) { int current = currentConcurrency.get(); if (current + count > maxConcurrency) { return false; } if (currentConcurrency.compareAndSet(current, current + count)) { return true; } } }

注意这里不会真的创建一个java.util.concurrent.Semaphore对象,而是用自旋 CAS 维护一个计数值。为什么这样设计?因为真正的Semaphore内部有同步队列、许可管理等复杂逻辑,在高并发下可能涉及线程挂起和唤醒,开销远高于一个AtomicInteger的自旋 CAS。

线程数限流的开销主要有两个:

  1. 每次请求的 acquire 和 release:各是一次 CAS 操作,开销极低。即使 10000 QPS 也就两万次 CAS,纳秒级操作,对整体性能几乎没有影响。
  2. 无额外内存开销:一个AtomicInteger4 个字节,加上一个 int 阈值,比滑动窗口省太多了。

所以单从性能角度讲,线程数限流比 QPS 限流更轻量。这个结论可能和不少人的直觉相反——大家总觉得线程数限流要"跟踪每个线程"很重,实际上 Sentinel 只是维护一个并发计数,并没有真的去监控每一个线程的生命周期。

4.3 不同并发量级的实测对比参考

用我个人在一个低配测试环境(4C8G 虚拟机、OpenJDK 8、单接口无下游依赖)跑过的对比数据作为参考:

压测并发QPS 限流开销(额外耗时/请求)线程数限流开销(额外耗时/请求)
100 QPS约 0.05ms约 0.01ms
1000 QPS约 0.08ms约 0.02ms
5000 QPS约 0.15ms约 0.04ms

这个数据不是严格基准测试,但趋势很明确:线程数限流在耗时和内存上的优势都更明显。不过要注意,单机性能差异在实际生产环境通常不是决定性因素,选型更应该看业务场景的匹配度,而不是纠结这零点几毫秒的差距。

5. 动态配置实操:Sentinel 整合 Nacos 实现 QPS 和线程数限流热更新

5.1 为什么推荐用 Nacos 做 Sentinel 规则持久化

先回答一个常见问题:Sentinel 的规则默认是存在内存里的,应用重启就丢了。虽然控制台可以手动推规则,但生产环境多实例部署时,手动推送很容易漏发或者覆盖,而且一旦应用重启,规则就全部清空,非常危险。

用 Nacos 做规则持久化有几个实际好处:

  • 规则可以走 Git 管理,变更可审计,回滚也方便。
  • 多个实例只要订阅同一个 dataId,规则变更自动推送到所有节点,不需要逐台操作。
  • 应用重启后会自动从 Nacos 拉取规则,不用每次上线重新配置。

我自己在多个项目里用的都是这种方式,稳定跑了很久,没有遇到过规则丢失的问题。

5.2 引入依赖与基础配置

假设你的项目已经接了 Spring Cloud Alibaba,需要额外引入 Sentinel 数据源适配 Nacos 的依赖:

<!-- Sentinel 核心依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2021.0.5.0</version> </dependency> <!-- Sentinel Nacos 数据源依赖 --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>1.8.7</version> </dependency>

如果你的项目没有用 Spring Cloud Alibaba,而是原生 Spring Boot + Sentinel,那就单独引入这两个依赖:

<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> <version>1.8.7</version> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>1.8.7</version> </dependency>

版本方面,我用的是 1.8.7,目前生产环境也用的这个版本,比较稳定。如果你用的是更新的 1.8.8 或 2.0 系列,接口基本兼容,但建议先看官方文档确认FlowRule类的变化。

5.3 配置限流规则的 Nacos 样例

Nacos 控制台里新建一个配置:

  • Data ID:sentinel-flow-rules
  • 分组:DEFAULT_GROUP
  • 配置格式:JSON

内容如下,这里我同时写了 QPS 限流规则和线程数限流规则的样例:

[ { "resource": "submitOrder", "limitApp": "default", "grade": 1, "count": 1000, "strategy": 0, "controlBehavior": 0, "clusterMode": false }, { "resource": "queryUserOrders", "limitApp": "default", "grade": 1, "count": 500, "strategy": 0, "controlBehavior": 1, "clusterMode": false }, { "resource": "callDownstreamApi", "limitApp": "default", "grade": 0, "count": 50, "strategy": 0, "clusterMode": false } ]

字段含义说明:

  • resource:资源名,对应代码里SphU.entry(resource)或@SentinelResource(value = "...")的名称。
  • grade:限流模式,0表示线程数限流,1表示 QPS 限流。最容易搞错的一个字段。
  • count:阈值。grade=1时表示每秒最大 QPS,grade=0时表示最大并发线程数。
  • controlBehavior:流量控制效果,0直接拒绝,1匀速排队(仅 QPS 模式支持),2预热模式。
  • strategy:流控策略,0直接按资源本身限流,1按关联资源限流,2按链路入口限流。

上面样例里我配置了三条规则:submitOrder是 QPS 限流直接拒绝(默认行为),queryUserOrders是 QPS 限流匀速排队(适合削峰),callDownstreamApi是线程数限流(保护下游依赖接口)。实际项目中你可以按接口特征分别调整。

5.4 Java 侧加载 Nacos 数据源代码

在 Spring Boot 里配置一个FlowRuleDataSource的 Bean,启动时让它从 Nacos 拉取规则并监听变更:

import com.alibaba.cloud.sentinel.datasource.converter.SentinelConverter; import com.alibaba.csp.sentinel.datasource.ReadableDataSource; import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.List; @Configuration public class SentinelNacosConfig { @Bean public ReadableDataSource<String, List<FlowRule>> flowRuleDataSource() { // 参数:serverAddr, groupId, dataId, 转换器 // 注意这里的 groupId 是 Nacos 的配置分组,dataId 是配置的 Data ID ReadableDataSource<String, List<FlowRule>> dataSource = new NacosDataSource<>( "127.0.0.1:8848", "DEFAULT_GROUP", "sentinel-flow-rules", source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}) ); FlowRuleManager.register2Property(dataSource.getProperty()); return dataSource; } }

有一个容易踩坑的点:如果你是 Spring Cloud Alibaba 版本,推荐直接用它的SentinelDataSource注解方式,代码可以更简洁:

import com.alibaba.cloud.sentinel.annotation.SentinelDataSource; @Configuration public class SentinelNacosConfig { @SentinelDataSource("sentinel-flow-rules") private ReadableDataSource<String, List<FlowRule>> flowRuleDataSource; }

但有个前提:Spring Cloud Alibaba 的@SentinelDataSource只支持流控规则(FlowRule),如果你要配置降级规则(DegradeRule)、热点规则(ParamFlowRule),还是要手动写数据源并注册到对应的 Manager。我的做法是:流控规则用注解,其他规则手动注册,各用各的方式,互不干扰。

5.5 规则变更验证与可视化

配置好之后,启动应用,你会看到控制台日志里出现类似这样的输出:

[Sentinel] register property with property name: sentinel-flow-rules, data source: NacosDataSource

接着去 Nacos 控制台改一条规则(比如把count从 1000 改成 800),保存后:

  1. Sentinel 控制台对应资源的限流阈值会立刻变化,不用重启应用。
  2. 通过接口压测验证:在 Nacos 把阈值调低到 10,一秒钟发 20 个请求,后者就有 10 个被限流,证明动态生效。

这里有个小经验:Nacos 推规则到应用是最终一致模型,正常情况下是秒级生效,但极端情况下(网络抖动、Nacos 短暂不可用)会有延迟。核心链路别依赖"实时性"太强,建议在业务侧做好兜底,比如应用启动时加载本地备份规则。

5.6 控制台与 Nacos 之间的规则一致性坑

很多人会在 Sentinel 控制台上手动调整规则,同时又配了 Nacos 数据源,然后发现规则"莫名其妙被还原"。原因是:Nacos 数据源注册后,Nacos 成为规则的唯一事实来源,控制台的修改只是改了内存态,一旦 Nacos 推送一次(哪怕内容没变),内存态就被覆盖恢复成 Nacos 的配置。

我的建议很简单:选择了 Nacos 持久化,就认准 Nacos 这一个配置入口。控制台只用来观测实时流量和规则生效情况,不要在控制台改规则。有规则变更需求,直接改 Nacos 配置,走代码评审和发布流程,这样更安全。

6. 从压测到上线:限流参数怎么定才靠谱

6.1 先做容量评估,再定阈值

限流参数我始终坚持一个原则:不压测、不设阈值。拍脑袋出来的数字,哪怕是经验丰富的架构师,也容易估算偏差。

具体操作流程:

  1. 单机压测找拐点:用压测工具慢慢增加并发,观察 CPU、内存、RT、错误率。找到"再往上加压,RT 开始线性暴涨、错误率上升"的那个点,这就是系统的软极限。
  2. 按软极限打折:QPS 限流取软极限的 70%~80%,线程数限流取线程池容量的 70%~80%(比如 Tomcat 200 线程,就设 140~160)。
  3. 预留高峰期 buffer:结合业务日常峰值、大促峰值,预留 30% 左右的余量。限流的作用是防系统过载,不是把系统永远压在 100% 负载。
  4. 灰度验证:先在低流量机房或少量节点上线规则,观察一周,确认没有误杀再全量。

6.2 压测环境容易忽略的点:慢请求制造

很多人压测用的是固定并发短请求,这对 QPS 限流参数的定标来说其实不够。我建议专门做两轮压测:

  • 第一轮:常规压测,也就是大家都做的,测出正常耗时下的 QPS 基线。
  • 第二轮:慢请求压测,用工具给部分请求注入延迟(比如通过 mock 下游增加 2s 延迟),看看 QPS 限流模式下线程池会不会被打满。这一步非常能说明该不该上线程数限流。

我试过一个小实验:单机 4C8G,Tomcat 默认 200 线程,一个接口正常耗时 30ms,QPS 限流设 1000,压测时平均 RT 到了 3000ms——结果线程池耗尽,P99 飙到 5000ms,大量请求超时。后来给这个接口加了线程数限流 150,同样模拟慢请求,P99 稳定在 800ms 以内,错误率也大幅下降。

6.3 限流后的响应处理:别让客户端一脸懵

限流触发后,Sentinel 默认抛BlockException,如果你的全局异常处理器没接住,用户看到的就是一堆堆栈信息,非常不友好。

实际开发中建议统一处理:

import com.alibaba.csp.sentinel.slots.block.BlockException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @ControllerAdvice public class SentinelBlockHandler { @ExceptionHandler(BlockException.class) @ResponseBody public String handleBlock(BlockException e) { // 这里可以根据 e.getRule().getGrade() 判断是 QPS 限流还是线程数限流 int grade = e.getRule().getGrade(); String mode = (grade == 0) ? "并发数超限" : "访问量超限"; // 业务侧可以返回一个友好的 JSON,比如 {"code": 429, "message": "系统繁忙,请稍后再试"} return "{\"code\":429,\"message\":\"系统繁忙(" + mode + "),请稍后再试\"}"; } }

还有一点:限流返回的 HTTP 状态码最好用 429(Too Many Requests),别用 500。500 会让上游误以为系统故障而触发重试风暴,429 则明确表达"请求过多",合理的调用方会做退避。如果你用的是 OpenFeign 或 Dubbo 调用,也要保证调用方对 Block 结果有兜底处理,比如降级缓存或走备用通道。

6.4 压测工具推荐与参数参考

常规压测工具我常用的三款:

  • JMeter:老牌工具,适合多协议压测,脚本复用性好。
  • wrk:轻量级 HTTP 压测工具,压单接口很方便,秒级就能看结果。
  • Locust:python 编写,适合编排复杂场景,模拟不同用户行为。

压测参数参考(单机 4C8G,一个简单 HTTP 接口):

# wrk 压测示例:8 线程模拟连接,持续 30 秒,逐步加并发观察 wrk -t8 -c100 -d30s --latency http://your-service:8080/api/test wrk -t8 -c200 -d30s --latency http://your-service:8080/api/test wrk -t8 -c500 -d30s --latency http://your-service:8080/api/test

把三次结果的 QPS、RT、错误率记录下来,绘制一条"并发 vs QPS"的曲线,拐点就是容量极限。

7. 我们项目最终采用的配置方案与后续扩展

最后分享一下目前项目里的实际用法,可以当成参考模板。

核心交易链路的三个接口配置如下:

接口模式阈值原因
下单提交(submitOrder)QPS + 线程数双限流QPS 800,线程数 150核心入口,既要防瞬时峰值,又要防下游变慢拖死线程池
订单查询(queryOrder)QPS 限流2000纯查询,依赖的 Redis 和 DB 性能稳定
外部物流状态回写(logisticsCallback)线程数限流60外部依赖不可控,只用线程数保护

配置方式:规则统一放 Nacos,由代码仓库管理,改动走 MR + Review。监控方面,Sentinel 控制台显示实时流量,另外把 Blocked QPS 指标接入 Prometheus + Grafana,设置了告警:当某资源 Blocked QPS 超过正常流量的 10% 时告警,避免限流都默默发生了还没有人发现。

后续扩展方向我在考虑两件事:

  • 熔断降级细化:目前只做了限流,降级规则(慢调用比例、异常比例)还没完全铺开,下一步想对依赖的下游接口逐个加上。
  • 热点参数限流:下单接口里某些热门商品 ID 的流量远超其他商品,单靠资源级 QPS 限流不够精细,热点参数限流可以只对个别 key 生效,更精准。

根据我在实际项目中的体会,QPS 限流和线程数限流不是二选一的关系,更像是"入口守门员"和"内部容量保护者"的分工。初期系统简单、接口耗时稳定时,QPS 限流完全够用;当系统复杂度上来了,外部依赖一多,线程数限流几乎成了必备。配置前多做一轮压测,上线后盯几天监控,你会发现这两道防线配好了,系统的稳定性会有一个非常明显的提升。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 9:19:14

Golang四方支付系统源码实战:从能跑到敢收单的架构与避坑指南

简介&#xff1a;这是一套用 Golang 编写的四方支付系统完整源码&#xff0c;面向具备一定后端基础、希望深入理解支付业务链路的开发者与二次开发团队。四方支付平台连接商户、消费者、银行及第三方支付机构&#xff0c;源码覆盖订单创建、支付接口调用、状态同步、退款处理等…

作者头像 李华
网站建设 2026/10/20 12:03:08

Office激活失败怎么办?从许可证分类到修复全流程

“您的Office尚未激活。”这句话我处理过太多次了。以前用户遇到这种黄色提示&#xff0c;第一反应就是去网上找“激活工具”&#xff0c;结果往往越搞越糟糕——轻则激活状态从“未激活”变成“已损坏”&#xff0c;重则整个Office打不开&#xff0c;甚至电脑里被塞进一堆垃圾…

作者头像 李华
网站建设 2026/10/20 12:03:08

Windows蓝屏自救指南:从终止代码到硬件排查的思路与实践

前些日子一个老朋友跟我诉苦&#xff1a;电脑凌晨三点还在“蓝屏→重启→蓝屏”的循环里挣扎&#xff0c;而第二天一早交方案。说实话&#xff0c;只要用过 Windows&#xff0c;没人没见过那面蓝色大墙&#xff0c;它的正式名字叫 Bug Check&#xff08;内核错误检查&#xff0…

作者头像 李华
网站建设 2026/10/20 12:03:07

图灵奖得主用Claude Code破解数学难题:AI如何成为科研第一助手

最近科技圈最激动人心的新闻&#xff0c;不是哪家又发布了新款芯片&#xff0c;也不是大模型又在哪个榜单上刷新成绩&#xff0c;而是一位88岁高龄的图灵奖得主&#xff0c;拿着Claude在一个小时之内攻破了一道困扰数学界30年的悬案。消息出来我第一时间就去翻了相关帖子和讨论…

作者头像 李华
网站建设 2026/10/22 21:31:59

GPU资源池化五步法:从硬件抽象到计量回收的工程实践

1. GPU 利用率困局&#xff1a;为什么你的卡明明买了却总在“摸鱼”做企业级 AI 基础设施这行十来年&#xff0c;我见过太多机房里堆着几十上百张卡、账面算力看着很唬人、实际利用率却长期趴在 15% 到 30% 之间的场景。老板看着采购单心疼&#xff0c;算法团队抱怨排队排到天亮…

作者头像 李华