API 网关与限流熔断降级完全指南:别让流量高峰把系统一波带走

API 网关不是转发器那么简单。本文系统讲清网关在认证、路由、限流、熔断、降级、灰度、观测中的职责,结合真实流量高峰场景,给出可落地的限流算法、熔断策略与故障隔离设计。

18 分钟阅读
小明

API 网关与限流熔断降级完全指南:别让流量高峰把系统一波带走

很多系统真正崩掉的那一刻,不是机器突然坏了,而是请求太诚实了。

用户来得太多,请求一个不落地全打进来,下游一个比一个努力,最后全链路一起趴下。

这时候你会发现,系统不是死于“没有功能”,而是死于没有边界

  • 没人拦住异常流量
  • 没人把不同租户、不同接口、不同依赖分开对待
  • 没人决定什么时候该拒绝,什么时候该降级,什么时候该快速失败

API 网关存在的价值,就在这里。

很多团队把网关理解成:

  • 路由转发
  • 统一鉴权
  • 配几个 header

这些当然都是网关的工作,但远远不够。

一个真正成熟的网关层,承担的是:

  1. 流量入口治理
  2. 接口访问控制
  3. 系统自我保护
  4. 灰度和观测枢纽

这篇文章想讲清楚的,不是“网关是什么”,而是:

  • 什么时候需要 API 网关
  • 限流该放在网关、应用还是下游
  • 熔断和降级到底在保护谁
  • 怎样设计高峰期的系统保护策略
  • 网关做太多会不会变成新的单点风险

如果你经历过大促、活动抢购、开放平台调用洪峰,这篇会很实用。


一、先讲本质:网关是入口层的交通警察,不是纯转发器

没有网关时,请求通常直接进入不同服务。看起来简单,但规模一大就会暴露问题:

  • 认证逻辑散落各服务
  • 流量策略不统一
  • 错误码和限流口径不一致
  • 灰度、黑白名单、租户控制无统一入口
  • 一旦攻击或流量异常,保护动作只能各自为战

网关真正解决的,是把这些“入口问题”收口到一层。

1.1 网关最核心的四类职责

职责解决什么问题为什么适合放网关
认证与鉴权谁能进、能进到哪入口统一最省重复
路由与协议转换请求应该去哪里客户端和内部拓扑解耦
流量治理谁能进多少、何时拒绝入口层最先看到总流量
观测与灰度看得见、控得住最适合做统一埋点和分流

1.2 但网关不该做什么

常见错误是把网关做成“什么都能塞的地方”:

  • 大量业务规则放网关
  • 复杂聚合逻辑放网关
  • 数据库存取放网关
  • 长耗时计算也放网关

这样做的结果通常是:

  • 网关越来越胖
  • 入口层故障影响面最大
  • 调试复杂度飙升
  • 所有团队都来改网关

网关要做的是保护和治理入口,不是替代后端业务层。


二、什么时候真的需要网关

2.1 三种非常典型的场景

场景 A:客户端多,后端服务也多

Web、App、小程序、开放平台都在访问不同服务,如果没有网关,认证、限流、协议适配会在每个服务里重复实现。

场景 B:入口流量不均匀且高峰明显

比如活动会场、抢购、开放 API 调用,这些请求会呈现明显峰值,没有入口层保护很容易直接把后端打穿。

场景 C:需要统一治理能力

包括:

  • 黑白名单
  • 限流规则
  • 风险控制
  • 灰度发布
  • 统一日志和 tracing

这些事情放在服务内部做,不但重复,还很难保证口径一致。

2.2 什么情况下别把网关搞太重

如果系统还很小、入口单一、流量平稳,过早做重量级网关平台可能收益不大。先用轻量代理 + 统一中间件,也许更合适。

问题不在于“有没有网关”,而在于:

你的入口复杂度,是否已经大到值得为统一治理单独付出成本。


三、限流到底限什么:不是只限 QPS,而是限风险

很多人第一次做限流,最先想到的是:

每秒最多 1000 个请求。

这个思路太粗。

系统真正需要限制的,通常是不同维度上的风险暴露:

  • 某个租户打得太猛
  • 某个用户在刷接口
  • 某个热点活动流量突然爆发
  • 某个高成本接口被持续滥用

所以限流不只是“全局一个数”,而是分层次的。

3.1 常见限流维度

维度适用场景例子
全局限流保护整体系统总入口每秒不超过 5 万
接口限流高成本接口保护下单接口每秒不超过 2000
用户限流防刷、防滥用单用户每分钟 60 次
租户限流多租户隔离大客户不能把中小客户挤死
下游限流保护稀缺依赖调支付网关 QPS 不超过 500

3.2 限流的目的不是“公平”,而是“保核心”

大促期间最重要的,不一定是让所有请求都进来,而是让:

  • 下单主链路优先
  • 登录和支付优先
  • 非核心接口必要时降级或直接拒绝

这叫流量分级

没有分级的限流,很多时候只是平均地拒绝所有人,听起来公平,业务上很亏。


四、常用限流算法,到底怎么选

4.1 固定窗口:简单,但边界突刺明显

固定窗口就是每个时间窗口统计一次。

优点:好实现。

缺点:边界时刻可能双倍突刺。

例如最后 1 秒打满 100 次,下一秒开头再打满 100 次,短时间会冲出 200 次。

4.2 滑动窗口:更平滑,但实现稍复杂

把统计窗口细分后滑动计算,更贴近真实流量。

适合:

  • 风险控制接口
  • 对突刺更敏感的依赖

4.3 令牌桶:适合控制平均速率,同时允许有限突发

这是工程里最常见也最好用的一类算法。

  • 令牌按固定速率生成
  • 请求来时拿令牌
  • 有令牌就放行
  • 没令牌就拒绝或排队

优点:既能控制长期速率,又能容忍短时突发。

4.4 漏桶:适合把突发流量整形成稳定输出

如果下游系统承受不了尖峰,漏桶更适合。它强调固定流出速率

适用于:

  • 某些老旧下游系统
  • 第三方依赖调用
  • 对流量平滑性要求更高的链路

4.5 一个简单的令牌桶示例

class TokenBucket {
  private tokens: number
  private lastRefillAt: number

  constructor(
    private capacity: number,
    private refillPerSecond: number,
  ) {
    this.tokens = capacity
    this.lastRefillAt = Date.now()
  }

  allow(): boolean {
    const now = Date.now()
    const elapsedSeconds = (now - this.lastRefillAt) / 1000
    const refill = Math.floor(elapsedSeconds * this.refillPerSecond)

    if (refill > 0) {
      this.tokens = Math.min(this.capacity, this.tokens + refill)
      this.lastRefillAt = now
    }

    if (this.tokens <= 0) {
      return false
    }

    this.tokens -= 1
    return true
  }
}

线上通常不会直接用进程内版本做全局限流,但这段代码能说明核心思想。


五、限流该放哪一层:网关、应用、还是下游

正确答案通常不是“选一个”,而是分层限流

5.1 网关限流:挡住最前面的风险

适合:

  • IP / 用户 / 租户维度控制
  • 公开 API 防刷
  • 活动入口洪峰控制
  • 黑白名单和风控前置

5.2 应用层限流:保护具体业务能力

适合:

  • 某个高成本业务逻辑
  • 某个热点聚合接口
  • 依赖某些昂贵资源的场景

5.3 下游依赖限流:保护最脆弱资源

适合:

  • 支付渠道
  • 短信服务
  • 搜索集群
  • 老系统或第三方接口

一个成熟体系通常是:

网关先挡总流量和明显异常
应用层控制业务热点和高成本路径
依赖调用侧再保护具体下游

如果只在最末端限流,你等于让大部分无效请求已经穿过了整个系统。


六、熔断到底在保护谁

很多人以为熔断是“某个接口挂了就报错”。其实它真正保护的是:

  1. 调用方线程池 / 连接池
  2. 下游已经不健康的系统
  3. 整条调用链的剩余可用性

6.1 一个典型故障传播过程

没有熔断时:

  • 下游服务变慢
  • 上游请求持续堆积等待
  • 线程池、连接池被占满
  • 更多请求开始超时
  • 整个系统逐步雪崩

有熔断时:

  • 检测到错误率或延迟异常
  • 快速失败,停止继续压下游
  • 触发降级逻辑
  • 给下游恢复窗口

这就是为什么熔断不是“放弃请求”,而是保护整体系统存活

6.2 熔断的三个状态

  • Closed:正常放量
  • Open:直接拒绝,走降级
  • Half-Open:小流量试探恢复情况

6.3 一个简单示例

type BreakerState = 'closed' | 'open' | 'half-open'

class CircuitBreaker {
  private failures = 0
  private openedAt = 0
  private state: BreakerState = 'closed'

  constructor(
    private failureThreshold: number,
    private recoveryTimeoutMs: number,
  ) {}

  canRequest() {
    if (this.state === 'open') {
      if (Date.now() - this.openedAt > this.recoveryTimeoutMs) {
        this.state = 'half-open'
        return true
      }
      return false
    }
    return true
  }

  recordSuccess() {
    this.failures = 0
    this.state = 'closed'
  }

  recordFailure() {
    this.failures += 1
    if (this.failures >= this.failureThreshold) {
      this.state = 'open'
      this.openedAt = Date.now()
    }
  }
}

真实生产里会基于时间窗口、错误率、慢调用比等更细指标来做,但逻辑核心一致。


七、降级不是认输,而是给核心路径让路

降级最容易被误解成“功能阉割”。

更准确的理解是:

在资源紧张或依赖异常时,优先保住最核心链路。

7.1 常见降级策略

策略适用场景例子
返回兜底数据推荐、榜单、装饰性模块推荐位返回默认内容
关闭非核心能力评论、收藏、营销提示秒杀时临时关闭评论摘要
只读模式写链路异常时订单查询可用,下单暂缓
预计算结果配置、榜单、静态聚合活动页直接返回缓存快照

7.2 降级必须提前设计,不是故障时临场发挥

如果系统只有“全功能运行”和“完全报错”两种状态,那它在高峰时会很脆。

成熟团队会提前定义:

  • 哪些接口是 P0,必须保
  • 哪些功能可弱化
  • 哪些返回可以用旧数据兜底
  • 哪些依赖超时后直接放弃

7.3 一个降级例子

export async function getHomepageData(userId: string) {
  const [banner, flashSale, recommendations] = await Promise.all([
    bannerService.getBanner(),
    flashSaleService.getFlashSale().catch(() => null),
    recommendationService.getRecommendations(userId).catch(() => []),
  ])

  return {
    banner,
    flashSale,
    recommendations,
    degraded: !flashSale || recommendations.length === 0,
  }
}

这里不是“所有失败都吞掉”,而是清楚地区分:

  • 哪个能力失效还能接受
  • 哪个能力不能影响主页面可用

八、网关层还能做什么:灰度、隔离、观测

8.1 灰度发布

网关是最适合做流量分流的地方。可以按:

  • 用户 ID
  • 租户
  • 地区
  • header
  • cookie
  • 实验桶

把小部分流量导入新版本。

8.2 租户隔离和优先级保护

多租户系统常见问题是,大客户或异常租户把公共资源吃满。

网关层适合做:

  • 租户配额
  • 优先级通道
  • 不同 SLA 的差异化限流

8.3 统一观测

网关能天然拿到:

  • 接口入口 QPS
  • 状态码分布
  • 限流命中次数
  • 熔断次数
  • 下游路由分布
  • 延迟分位数

如果没有这层观测,你通常会在故障后才意识到:

  • 到底是入口打爆了
  • 还是某个下游先慢了
  • 还是某个租户在恶意刷接口

九、网关本身也会变成风险点,怎么避免

这点必须讲透。

API 网关治理得好,是保护层;治理得差,它自己就是最大的单点风险。

9.1 常见问题

  • 网关逻辑过重
  • 所有新需求都往网关里塞
  • 配置变更缺少审计
  • 单实例或单集群承压过高
  • 限流和熔断策略全是手工临时修改

9.2 防止网关变成“超级单点”的做法

  1. 网关只做入口治理,不做重业务
  2. 网关配置要版本化和审计化
  3. 网关自身也要水平扩展
  4. 网关规则改动要支持灰度
  5. 网关要有独立的限流 / 熔断 / tracing 观测

9.3 一张职责边界表

能力放网关放业务服务
认证鉴权可补充细粒度权限
路由转发
IP / 用户基础限流可补充
复杂业务规则
聚合多个领域数据谨慎,少量✅ BFF / 服务层
数据库存取

十、一个完整的高峰保护方案长什么样

以大促会场为例,可以这样设计:

第 1 层:CDN + 边缘缓存

静态资源、弱动态配置先在最外层吸收重复访问。

第 2 层:网关总入口限流

按 IP、用户、租户、接口级别做第一轮流量裁剪。

第 3 层:应用层热点接口限流

例如下单、优惠计算、抢购资格校验。

第 4 层:依赖熔断与降级

营销、推荐、评论等非核心依赖一旦变慢立即降级。

第 5 层:数据层保护

库存、订单、支付链路再做最后的容量保护和优先级保障。

10.1 一个真实收益对比示例

某次活动页治理前后:

指标优化前优化后
高峰入口 QPS6200062000
应用层实际承压 QPS4100014000
下单接口超时率7.2%0.8%
推荐服务错误扩散影响主链路被隔离
大促扩容实例数4826

这就是入口治理的价值:不是流量变少了,而是无效流量和非核心流量不再把全系统一起带崩。


十一、给团队的 API 网关与流量治理检查清单

网关职责层

  • 是否明确网关只做入口治理,不承载重业务
  • 是否统一了鉴权、路由、基础限流和观测
  • 是否支持灰度和快速回滚

限流策略层

  • 是否区分全局、接口、用户、租户、下游维度
  • 是否按业务优先级做分级保护
  • 是否有热点接口专项策略

熔断降级层

  • 是否对关键下游做了熔断
  • 是否提前设计了降级返回
  • 是否支持半开试探恢复
  • 是否对失败重试有边界控制

观测治理层

  • 是否能看到限流命中和熔断次数
  • 是否有入口到下游的 tracing
  • 是否能识别某个租户或接口异常放量
  • 是否有高峰保护演练

总结

把 API 网关、限流、熔断、降级讲透,可以收敛成 5 句话:

  1. 网关的核心价值是统一入口治理,不是单纯转发。
  2. 限流限的不是请求数,而是系统风险暴露。
  3. 熔断保护的是整条调用链,不只是某个下游。
  4. 降级不是认输,而是让核心路径继续活着。
  5. 真正成熟的方案一定是分层治理:边缘、网关、应用、依赖各有职责。

如果你只记住一句话,我希望是这一句:

好的入口治理,不是让所有请求都进来,而是让最重要的请求在最糟糕的时候也能进来。

否则高峰一到,系统最先学会的不是弹性,而是——

集体躺平。