别再说单体不需要限流熔断
别再说单体不需要限流熔断
很多团队觉得限流熔断是微服务网关的事,单体应用只要加机器就行。这个想法在流量平稳时没问题,一旦某个接口慢,线程池被占满,整个进程都会失去响应。我们做过一个真实事故复盘:订单服务里调库存 RPC 超时,300 个 Tomcat 线程全卡在连接等待上,健康检查失败被 K8s 反复重启,重启后又立刻被打满,形成重启风暴。
限流不是挡外部用户,是保进程自身;熔断不是隔离网络,是隔离故障传播。这两件事跟服务拆不拆没有必然关系。
限流要分入口和内部两条线做
入口限流大家熟悉,通常用令牌桶按 QPS 控制外部请求。但更常见的问题是内部调用失控:比如一个查询接口按商品列表循环调库存服务,外部限 100 QPS 挡不住它内部放大成 1000 次调用。
- 入口限流按接口维度配置,用 Guava RateLimiter 或 Sentinel 的
FlowRule,阈值建议取压测通过 QPS 的 70%,给突发流量留缓冲。 - 内部调用限流按下游资源维度加,比如库存查询单独一个信号量或 RateLimiter,防止循环调用把下游打挂。
- 异步任务线程池也要限,队列长度和拒绝策略必须显式配置,不要用无界队列掩盖过载问题。
熔断的粒度要按调用路径切
单体服务里熔断器不能只做全局开关,否则误伤太大。我一般按"下游目标 + 业务路径"双维度做熔断。比如同样是调支付服务,下单路径和退款路径的熔断要独立配置,因为退款链路慢可以容忍,下单链路慢会直接影响转化。
实操层面,熔断器的触发条件别只看错误率。我们线上踩过坑:接口错误率没到阈值,但 P99 已经飙到 5 秒,请求全挂在超时等待上。后来把熔断条件改成 错误率 OR 平均耗时,并且耗时窗口用滑动时间窗口,至少覆盖一个完整调用周期。
- 熔断恢复用半开状态试探,初始请求数要小,比如 5 个,避免恢复瞬间又被压垮。
- 熔断后必须有明确降级动作:返回缓存、跳过非核心步骤,或者快速失败给用户友好提示。
- 别把所有下游都熔断成同一个开关,按资源隔离设计线程池,慢调用单独占池。
观测和演练不能只靠文档
限流熔断上线后最容易忘的是观测。没有指标的话,你根本不知道阈值是否合理,也不知道线上触发频率是不是异常。我们要求每个限流点和熔断器都必须埋点:当前 QPS、拒绝数、熔断状态、恢复次数,直接打点到 Prometheus。
阈值不是一次定终身,要跟着容量变化定期校准。每次大促或架构变更后,至少跑一次故障演练,把下游延迟拉到阈值边界,观察限流和熔断是否能按预期触发,进程是否能自保。
- 点赞
- 收藏
- 关注作者
评论(0)