单体服务不等于一个故障域

举报
yd_257405204 发表于 2026/10/21 09:09:57 2026/10/21
【摘要】 单体服务不等于一个故障域 很多团队觉得限流熔断是微服务才需要的东西,单体应用一个进程,挂了就重启。真实情况是:单体里所有接口共享同一个 Tomcat 线程池( server.tomcat.max-threads 默认 2

单体服务不等于一个故障域

很多团队觉得限流熔断是微服务才需要的东西,单体应用一个进程,挂了就重启。真实情况是:单体里所有接口共享同一个 Tomcat 线程池(server.tomcat.max-threads 默认 200)和同一个 HikariCP 连接池。一个运营后台的批量导出接口卡住 30 秒,200 个线程被占满,剩下的下单、登录接口全部排队超时,P99 从 80ms 涨到 12s。这就是雪崩,而它发生在单体里。更麻烦的是,单体里没有服务网格帮你兜底,任何保护都得自己在代码层做。

入口限流:按接口维度设闸门

在 Servlet Filter 里做最省事,不要用 Guava RateLimiter——它的 acquire() 是阻塞的,本身就会占线程。用 Bucket4j 的非阻塞接口:

  • Bucket.builder().capacity(500).refillGreedy(500, Duration.ofSeconds(1)).build(),调用 tryConsume(1) 返回 false 就直接回 429,不排队。
  • 维度选「接口路径 + 用户 ID」两级:单用户防刷,单接口防热点。别只做全局限流,一个热点接口就能吃光全局配额。
  • 阈值不要拍脑袋。压测拿到该接口 CPU 65%、P99 稳定时的 QPS,取 70%~80% 作为阈值。比如下单接口压到 800 QPS 时开始劣化,阈值设 550。
  • 再加一层全局兜底配额(比如整机 2000 QPS),防止几十个接口同时小幅超限叠加成灾难。

熔断:粒度是依赖,不是接口

最常见的错误是给每个接口配一个熔断器。20 个接口都在调同一个支付网关,各自统计失败率,每个都不到 50% 阈值,熔断永远不触发。正确做法是一个下游依赖共用一个熔断器:同一个 OkHttp Client、同一个 Redis 集群、同一个第三方 API,各自一个实例。

Resilience4j 的典型配置:滑动窗口 COUNT_BASED 100 次,failureRateThreshold 50,slowCallDurationThreshold 1s,slowCallRateThreshold 60,waitDurationInOpenState 30s,半开只放 permittedNumberOfCallsInHalfOpenState 10 次。注意慢调用也要计入失败,很多故障不是报错而是变慢。

熔断之前必须先把超时设对,否则熔断没有意义:连接超时 200~500ms,读超时 1~2s,用 OkHttp 的 callTimeout 或 Resilience4j 的 TimeLimiter 卡住总耗时。默认的无限等待会让熔断器永远统计不到失败。

隔离与降级:让故障只烂在一个角落

  • 慢依赖用 Bulkhead 线程池隔离,信号量模式适合低延迟本地调用,线程池模式适合外部 HTTP。给导出、报表这类重接口单独一个线程池,别和主链路抢。
  • 降级要写在熔断回调里,返回缓存快照或空列表,并打一个 degraded=true 的 tag 到 metrics,否则降级了没人知道。
  • 重试和熔断不要叠在同一个调用上。熔断打开时重试会把流量放大 3 倍,直接打穿下游。重试放在熔断器外层,且只对幂等接口开。

落地顺序与踩坑

按这个顺序做,收益递减但风险也递减:先补超时 → 再上熔断 → 再上入口限流 → 最后做线程池隔离。前两步能挡住 80% 的事故。

两个坑值得提前说:一是所有阈值必须走配置中心(Nacos / Apollo)动态下发,出事时能现场调,不能靠发版;二是把熔断器状态、限流拒绝数、线程池队列长度暴露到 Prometheus,Grafana 上单独一个面板看 circuitbreaker_state,半开状态放量失败要能第一时间看到。限流熔断不是加个注解就完事,它需要被观测、被演练,否则只是代码里的一段装饰。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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