BACKEND AVAILABILITY FIELD GUIDE

后端可用性设计
让故障“可控地发生”

可用性不是“永不失败”,而是当依赖变慢、流量突增、机器故障时,系统仍能保护核心链路、快速恢复,并给用户一个可理解的结果。用电商下单案例,一次学会超时、重试、熔断、隔离、限流与降级。

01一张图建立心智模型:先保护容量,再争取成功

可用性保护域 · 每一层都有明确预算 用户流量正常 + 突发 + 重试 入口限流令牌桶 / 429先挡住超过容量的流量 订单服务总截止时间 800ms重试预算 ≤ 2幂等键 order_id 依赖保护器超时 + 熔断独立信号量 20有界队列 / 快速失败 支付 / 库存依赖有限容量,会慢、会错P99 / 错误率 / 饱和度 异步削峰Kafka / Queue非实时任务延后处理 缓存 / 兜底数据过期可读 / 默认值 / 热门榜明确来源与新鲜度 削峰接纳调用探测 设计顺序① SLO 与容量→ ② 分层超时→ ③ 有界重试→ ④ 隔离 + 熔断→ ⑤ 限流 + 降级→ ⑥ 观测与演练 业务服务保护策略数据/依赖消息总线

SLO 是起点

例:月可用性 99.95%,错误预算约 21.6 分钟。没有目标,就无法判断该花多少钱、容忍多少降级。

超时是地基

没有超时,线程与连接会无限等待;后面的重试、熔断、隔离都失去可信边界。

有界是共同原则

次数有界、等待有界、并发有界、队列有界、降级范围有界。无限就是雪崩的别名。

02重试:只对“短暂且可恢复”的失败再试一次

发起调用deadline=800msAttempt N携带同一幂等键可重试?timeout / 502 / 503退避 + 抖动50 → 100 → 200ms成功 / 失败受总预算约束 4xx / 参数错 / 权限错 → 立即失败仍在 deadline 内且 attempts 未耗尽 放大系数 ≈ 1 + 重试次数;三层各重试 3 次,最坏可把 1 个请求放大为 27 次下游调用原则:只在一层重试;服务端返回 Retry-After;写请求用 idempotency-key / 去重表 / 状态机。

应该连接重置、超时、502/503/504

前提是请求可重复、仍有时间预算,并且退避带随机抖动,避免客户端同时再冲一次。

不要参数错、权限错、库存不足

确定性错误重试不会变好,只会增加延迟与负载。支付类写操作没有幂等键也不能盲重试。

必看指标attempts / success-after-retry

同时监控额外流量、重试后成功率与总延迟。成功率涨了但 P99 和下游负载爆了,仍是坏设计。

03熔断:依赖已经病了,就先别继续敲门

CLOSED · 关闭正常放行并统计滑动窗口错误率低于阈值OPEN · 打开不访问下游,立即失败/降级等待冷却窗口HALF_OPEN · 半开只放少量探测请求验证依赖是否恢复 窗口≥20 且失败率≥50%cooldown 到期探测成功 → 关闭探测失败 → 再次打开
熔断不是健康检查。它是调用方对某个依赖、某类调用的本地保护状态。按 host / endpoint / 租户合理拆分,避免一个坏分区拖累全部流量。

04隔离:像船的水密舱,坏一个依赖不沉整艘船

反例 · 所有依赖共享 8 个线程正例 · 每个依赖独立舱位 + 有界队列 共享线程池慢慢慢慢慢慢慢慢健康请求也排队线程耗尽 → 超时 → 重试 → 雪崩 推荐依赖舱● ● 满并发 2 · 超出即拒绝订单核心舱● ○ ○ ○并发 4 · 仍有容量连接池 / 线程池 / 信号量 / 队列都要独立且有上限拒绝比无限排队更可控:反馈快、容量可预测 Little's Law: 并发数 ≈ 到达率 × 平均响应时间;依赖慢 10 倍,所需并发也会膨胀 10 倍。隔离维度:核心/非核心、同步/异步、不同依赖、不同租户;同时设置队列长度与排队超时。

05限流:承认容量有限,把过载变成明确拒绝

突发请求8 requests now令牌桶● ● ● ● ●容量=5 · 固定速率补充服务稳定区5 × 200 · 3 × 429Retry-After 告知何时再来每秒补充 r 个令牌每请求消耗 1无令牌即拒绝 常见算法选择令牌桶:允许短突发漏桶:匀速输出滑动窗口:统计更准并发限制:直接保护线程/连接

限谁

全局、租户、用户、IP、API、资源成本。登录与导出报表不能使用同一个成本权重。

在哪里限

网关做粗粒度保护,服务内按业务成本二次限制,下游还要有自己的硬容量防线。

如何返回

HTTP 429 + Retry-After + 可识别错误码。客户端遵守退避,不能把拒绝变成重试风暴。

06降级:核心链路继续走,非核心体验暂时变简单

用户请求商品详情 / 下单是核心正确性?钱、库存、权限、订单状态兜底可信且可标记?缓存 / 默认 / 延后处理明确失败不要伪造核心业务成功核心数据不可降级支付未知 ≠ 支付失败执行降级热门榜 / 缓存 / 稍后通知是否是是
经典原则:宁可少功能,不可错账。 推荐、评价、画像可以降级;支付结果、库存扣减、权限校验必须保持正确语义,必要时返回“处理中/未知”并异步对账。

07经典案例:大促时推荐服务变慢,如何避免拖垮下单

事故链:推荐 P99 2s → 线程堆积 → 入口超时 → 客户端重试 → 流量放大 → 下单也不可用 流量 × 5客户端重试共享线程池满排队无上限订单请求超时核心被连坐更多重试正反馈回路系统雪崩 保护链:入口限流 → 推荐独立舱 → 150ms 超时 → 熔断 → 热门榜降级;订单核心舱保持可用 令牌桶超量 429推荐独立舱并发 20 / 队列 0150ms 超时不挤占总 deadline熔断快速失败停止无效调用热门榜兜底下单不受影响验证目标:订单成功率保持 ≥99.9%;推荐降级率可升高;入口拒绝可观察;推荐舱饱和不影响订单舱。

08必知必会:选型矩阵、上线清单与本地实验

策略解决什么关键参数最大风险核心指标
重试吸收瞬时故障次数、退避、抖动、总 deadline流量放大、重复写重试后成功率、额外调用量
熔断停止持续失败调用窗口、最小样本、阈值、冷却误熔断、全局化状态、拒绝数、半开成功率
隔离限制故障爆炸半径并发、池大小、队列、排队超时池太碎或容量错配池饱和度、排队时间、拒绝率
限流保护硬容量速率、突发量、维度、权重不公平、客户端重试风暴429、通过率、容量水位
降级保核心可用触发条件、兜底、新鲜度、恢复静默返回错误业务数据降级率、兜底命中、业务转化

上线前预算能否闭合

上游 deadline > 本地处理 + 下游 timeout + 有界重试退避。任何下游超时都不能超过剩余总预算。

演练不是只测成功路径

注入延迟、错误、连接耗尽与流量突增;观察策略是否按预期触发、恢复,并确认核心链路指标。

告警看用户结果而非机器

优先用 SLO、成功率、P99 与业务完成率告警,再用 CPU、线程池、熔断状态定位原因。

开始实验:进入 system-desgin/,运行 make check,再运行 make demo。单独观察可用 make retry、make circuit、make bulkhead、make rate-limit、make degrade。
$ cd system-desgin $ make serve PORT=8080 # 启动这份图谱 $ make demo # 运行全部策略实验 $ make circuit # 观察 CLOSED → OPEN → HALF_OPEN → CLOSED