为什么要给后端接口做限流和熔断降级

chinaz
chinaz 正式会员超兽战士
发布于 2026-10-07 09:35 ·1 浏览 ·0 回复

结论:限流是防止自己的服务被流量打死,熔断降级是防止自己被下游拖死——两者解决的不是同一个问题,任何对外提供服务的后端接口都应该同时具备,只做其中一个等于只系了一半安全带。

限流和熔断降级有什么区别?

限流(Rate Limiting)作用在入口,控制单位时间内允许多少请求进来;熔断(Circuit Breaker)作用在出口,当调用下游的失败率或慢调用比例超标时,主动切断调用、快速失败;降级(Fallback)是熔断或限流触发后返回的兜底结果。

三者的关系是:限流挡外面的洪水,熔断挡里面的塌方,降级负责让用户看到「稍后再试」而不是白屏。结论:限流保护的是服务自身的 CPU、连接数和线程池,熔断保护的是调用链上游不被下游的延迟传染。

不限流会怎么样?给几个具体场景

一个接口平时 QPS 200,数据库连接池 50 个连接,正常单请求耗时 30ms。突然来一波 5000 QPS 的爬虫流量,连接池瞬间占满,请求排队,耗时从 30ms 涨到 8 秒,紧接着上游调用方超时重试,流量翻倍,服务彻底不可用——这就是典型的流量雪崩。

后端接口限流的目的不是「拒绝用户」,而是在容量耗尽之前主动丢弃一部分请求,让剩下的请求保持 30ms 的正常响应。

限流阈值怎么定?

结论:限流阈值应按压测得出的单机容量 × 0.7~0.8 设置,而不是拍脑袋填 1000。压测出单机 1000 QPS 时 CPU 到 60%,那阈值就设 700~800 QPS,给突发和 GC 留出余量。

常用算法三种:计数器(简单但存在临界点双倍流量问题)、滑动窗口(精度高,Sentinel 默认统计窗口 1 秒)、令牌桶(允许一定突发,Guava RateLimiter 可设 500 QPS 且预存 100 个令牌)。

被限流的请求应返回 HTTP 429 Too Many Requests,并在响应头带 Retry-After: 1,让客户端知道 1 秒后重试,而不是返回 500 让调用方以为是服务故障。

熔断的三个状态是怎么工作的?

熔断器有三个状态:Closed(关闭,正常放行)、Open(打开,直接拒绝调用)、Half-Open(半开,放少量请求试探)。

典型配置:统计窗口 10 秒、最小请求数 20、错误率阈值 50% 或慢调用比例超过 50%(RT > 500ms),满足条件后进入 Open 状态并持续 5 秒;5 秒后进入 Half-Open,放行 10 个探测请求,若错误率低于阈值则回到 Closed,否则再次 Open。这套参数在 Sentinel 和 Hystrix 里都能直接配。

要注意隔离方式:线程池隔离每个下游独占 10 个线程、超时 1 秒,能防止慢调用阻塞主线程,代价是多几次线程切换;信号量隔离开销小但不支持超时中断,适合内部纯内存调用。

降级返回什么才不会被骂?

结论:降级要在设计阶段就定好兜底数据,而不是等熔断了才临时想返回什么。商品详情页的推荐模块挂了,返回空列表;用户头像服务挂了,返回默认头像;非核心的积分查询挂了,返回「积分稍后同步」。

兜底内容的优先级是:本地缓存 > 上一次成功结果 > 静态默认值 > 明确错误码。最不能接受的是返回一个格式正确但内容错误的数据,那比直接报错危害更大。

上线时最容易踩的三个坑

第一,只配超时不配熔断。下游 RT 从 50ms 涨到 3 秒,上游线程池 200 个线程在 200 个 × 3 秒内就会被占满,必须靠熔断在第 10 秒就切断。超时链路还要逐层递减:A 调 B 超时 800ms,B 调 C 超时 300ms。

第二,阈值写死不改。业务翻倍后限流阈值还是 700 QPS,正常流量被误杀。阈值应该配置化,随大促前压测结果调整,并配告警:触发限流超过 10 次/分钟就通知值班。

第三,只对写接口做限流。读接口同样会打满连接池,尤其是带复杂 SQL 的列表页和导出接口,这些往往才是最容易被刷的。

总结一下:限流在入口按 QPS 阈值挡住超额流量并返回 429,熔断在出口按错误率/慢调用比例切断故障下游,降级提供预先设计好的兜底数据。三者配合超时逐层递减,才能在单个依赖挂掉时保住整个调用链的可用性。

版权声明:本文来自 GJ站长论坛《为什么要给后端接口做限流和熔断降级》
原文链接:https://www.gj0.com/thread-208.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~