单体不是免死金牌:一次慢查询能拖垮整个 JVM

举报
yd_235578340 发表于 2026/11/06 10:24:22 2026/11/06
【摘要】 单体不是免死金牌:一次慢查询能拖垮整个 JVM 很多人觉得限流熔断是微服务才需要的东西,单体应用就一个进程,加了也没用。这个判断在流量平稳时看不出问题,但只要有一条链路变慢,整个进程都会被拖下水。我们线上有个订单服务,单

单体不是免死金牌:一次慢查询能拖垮整个 JVM

很多人觉得限流熔断是微服务才需要的东西,单体应用就一个进程,加了也没用。这个判断在流量平稳时看不出问题,但只要有一条链路变慢,整个进程都会被拖下水。我们线上有个订单服务,单体部署,Tomcat 默认 200 个工作线程。某次报表 SQL 漏了索引,单次查询 8 秒,运营后台的导出请求把 200 个线程全占满,前台下单接口跟着 502——它和报表毫无关系,只是共用了同一个线程池。

这就是单体的风险:故障域是共享的。线程池、数据库连接池、堆内存、CPU,任何一项被耗尽,所有接口一起挂。限流熔断在单体里的价值不是防外部攻击,而是把故障关进笼子里。

先做舱壁:把线程池和连接池按依赖切开

限流之前先隔离,否则会限错对象。具体三件事:

  • 给每个下游依赖(支付网关、短信、报表库、缓存)配独立的 ThreadPoolBulkhead 或信号量,比如短信 20 个并发、支付 50 个并发,超了直接拒绝而不是排队;
  • 数据库按业务拆连接池,报表走单独的只读池,maxPoolSize=8 写死,不和主库共用 HikariCP;
  • 所有跨进程调用强制设超时,HTTP 客户端 connectTimeout=500ms、readTimeout=2s,不允许是 0 或无限。

隔离做完,报表把只读池打满时,下单接口只是报表功能不可用,主流程照常。

限流:QPS 从压测数据来,不从感觉来

入口限流用拦截器加令牌桶,按接口维度配阈值。阈值必须来自压测:单机 P99 开始翘头时的 QPS,取 70% 作为线上阈值。我们下单接口压到 1200 QPS 时 P99 明显变差,阈值就设 800。

被限流的请求返回 429 并带 Retry-After,不要静默丢弃,否则上游会一直重试放大流量。关键依赖也加客户端限流,比如调用风控接口限制 300 QPS,超出走本地默认策略,比干等 2 秒超时体验好得多。

熔断:慢调用比例比异常率更早发现问题

熔断器只看异常率会漏掉慢调用——下游没报错,只是 RT 从 50ms 变成 3s,异常率还是 0。配置上要同时开两个条件:

  • 慢调用比例:统计窗口 10s,RT 超过 1s 记为慢调用,比例 > 50% 且请求数 ≥ 20 时熔断;
  • 异常比例:窗口内异常率 > 50% 且请求数 ≥ 20 时熔断;
  • 熔断 10s 后进入半开,放 5 个探针请求,成功再恢复。

请求数下限很重要:低峰期 2 个请求挂 1 个就是 50%,不加下限会频繁误熔断。

落地顺序和几个真实的坑

顺序建议是:超时 → 隔离 → 限流 → 熔断 → 降级。降级逻辑最后写,因为得先知道降级成什么业务语义。

  • 降级返回值要能被业务识别,比如库存查询降级返回 unknown 而不是 0,否则"查不到"会被当成"没库存",直接少卖;
  • 阈值放配置中心,但必须加变更审计,我们有过一次手滑把限流阈值改成 10,五分钟内全站 429;
  • 规则上线前用影子流量或压测环境验证,别直接在生产上调参数;
  • 把熔断状态、限流计数打进 Micrometer 指标并配告警,否则熔断了没人知道,等于没做。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。