Varidata 新闻资讯
知识库 | 问答 | 最新技术 | IDC 行业新闻
Varidata 知识文档

API 网关中的速率限制与熔断指南

发布日期:2026-09-17
API网关速率限制与熔断机制示意图

速率限制用于控制请求量,熔断用于阻止对不健康服务的持续调用。这两种模式都能保护你的 API,避免系统崩溃。设想一下秒杀场景:成千上万的请求会在同一时间打到你的 API 网关上。没有限制时,服务器会迅速变慢,直至几乎停摆。再设想某个下游服务发生故障:所有请求都会堆积在它后面,故障会扩散到整个平台。熔断器会在损害蔓延之前切断这个“生病”的服务。你将学习如何在 ngrok、Azure 和 Express.js 中配置速率限制与熔断机制。这些工具能让原本脆弱的流量系统从“硬扛到崩”变成“有弹性地承压不垮”。

为什么你的 API 网关需要保护

流量尖峰与过载

设想一次限时抢购活动。你的团队在中午发布一款限量产品。成千上万的用户会在同一时刻点击。你的 API 会立刻遭遇巨大的流量洪峰,服务器也会马上开始吃紧。响应时间会从毫秒级飙升到秒级,用户看到的将是不断旋转的加载图标和错误提示。这就是最典型的过载场景。如果没有保护机制,你的 API 网关无法放缓这波流量冲击。每一个新请求都会继续堆积,整个系统会在压力之下逐步失稳。限流提供了一种简单有效的手段:它能限制任意单个客户端发出的过量请求,让后端只处理可承受范围内的流量而不至于崩溃。过载保护能在需求激增时保持系统稳定。

流量模式可能在几分钟内就发生变化。一条爆款内容可能让你的访问量在短短数分钟内翻倍,而你的基础设施未必能如此迅速地扩容。云自动伸缩也需要时间来拉起新实例,因此你需要在负载变得危险之前,就在入口处设置控制机制。

级联故障与不健康依赖

一个变慢的下游服务,就足以拖垮整个系统。设想一个支付微服务开始响应迟缓。每个等待其返回结果的调用都会持续占用线程,更多请求会在后面排队,内存逐渐被耗尽。其他依赖支付服务的系统也会随之变慢,故障像连锁反应一样不断扩散。这种级联过载会非常迅速地摧毁可用性,几分钟内,整个平台就可能变得无法响应。

熔断器可以阻止这种级联效应。它会持续监控下游服务的健康状况。一旦错误率超过预设阈值,熔断机制就会打开,停止向故障服务继续发送流量。你的系统会快速返回降级响应,用户看到的是一条礼貌、明确的提示,而不是漫长的超时等待。系统中健康的部分仍然能够继续工作。

你的网关位于整个架构的最前端,所有入站流量都会先经过它。它能在异常模式蔓延之前先一步发现问题。保护 API,既要防范突发流量洪峰,也要防范缓慢恶化的系统退化。将速率限制与熔断结合起来,才能形成完整的防护体系。

速率限制:控制请求数量

速率限制用于限定客户端在设定时间窗口内可发起的请求数量。它会为每个客户端、IP、租户或路由设定最大请求预算,以保护共享容量并确保公平性。当客户端超过限制时,网关会返回 429 状态码。客户端如果能够在收到 429 后采用指数退避等正确行为,就能避免重试风暴进一步压垮系统。

速率限制的算法

四种算法覆盖了绝大多数场景。令牌桶允许短时间突发流量,但会限制持续性滥用。漏桶会将流量平滑成稳定的输出速率。固定时间窗口会在离散区间内统计请求数,因此在窗口边界可能出现突发。滑动窗口则跟踪一个持续移动的时间范围,从而避免这一边界问题。比如,一个智能投顾平台可以采用滑动窗口策略,为每位用户设置每 5 秒最多 100 次请求;而对于突发型客户端,设置为每个 key 每分钟 120 次请求、并允许 20 的突发容量的令牌桶策略也很合适。

如何在网关中配置速率限制

对写操作应当施加更严格的限制。创建记录的 POST 或 PUT 端点,理应比只读的 GET 端点拥有更紧的上限。按路由分别配置的方式,可以在抑制高成本操作被滥用的同时,仍然对读取操作保持相对宽松。

Spring Cloud Gateway 使用 YAML 路由定义。你可以通过 RequestRateLimiter 过滤器来配置速率限制:

spring:
  cloud:
    gateway:
      routes:
        - id: orders
          uri: http://orders-service
          predicates:
            - Path=/api/orders/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20

Azure Front Door 则通过 WAF 策略实现这一能力。你可以创建一条速率限制规则:将每个源 IP 限制为每分钟最多 1,000 个请求,并且只对 URL 中包含 /promo 的请求生效。该规则需要包含匹配条件、1 分钟或 5 分钟的持续时间,以及 Log 或 Block 动作。速率限制规则不支持 Allow。若要真正执行阻断,你还必须将策略从 Detection 模式切换到 Prevention 模式。

ngrok 提供了更简单的配置方式。你可以直接在 ngrok agent 配置或控制台中定义速率限制策略,按 IP 或按端点设置在某个时间窗口内的最大请求数。

按用户配额则是另一层防护。你可以从请求头中读取 API key 或用户 ID,然后对每个值分别应用独立计数器。标准套餐可能允许每分钟 120 次请求,而高级套餐可放宽到 1000 次。比如,金融科技的贷款资格评估 API 可以设置为每小时 1000 次调用,并按 token 成本计费;一个公开天气 API 则可以将每个 key 限制为每分钟 60 次请求。面向 token 的速率限制并非按原始请求数计量,而是按处理的 token 消耗计量,这种方式对于 AI 工作负载尤其适合,因为它能让成本控制更贴近真实资源消耗。

网关中的熔断机制

三种状态与一个简单比喻

可以把它想象成你家里的电路断路器。正常时它保持闭合,电流可以通过;电流过大时,它会跳闸断开;问题修复后,你再手动复位,电路恢复供电。软件熔断器也是同样的原理。在闭合状态下,网关会让所有调用正常通过;在打开状态下,它会停止向故障服务发送任何调用,并快速失败;在半开状态下,它只放行少量探测请求,用于判断服务是否恢复。如果探测成功,熔断器就重新闭合;如果探测失败,它会再次打开。

触发阈值决定熔断器何时切换状态。你可以设置为:在短时间间隔内达到一定数量的超时后打开熔断器,并保持打开一段时间。具体数值要根据你的服务级别目标来调整。设置得过低,正常抖动都可能触发熔断;设置得过高,则意味着用户已经承受了过多故障痛苦。

如何配置熔断器

回退端点能够让用户看到优雅降级后的响应,而不是生硬的错误。你应该主动为失败做设计,避免故障扩散。好的回退方案通常具备以下特征:

  • 向用户返回清晰、具体、可执行的信息,而不是笼统错误

  • 采用安全的重试逻辑,包括指数退避、最大重试次数和合适的超时时间

  • 对关键调用保证幂等性,避免重试造成重复副作用

  • 实现优雅降级,使用户旅程中至少一部分功能仍可继续使用

  • 提供明确的恢复路径,例如替代服务路由或离线模式

当熔断器打开时,你的代码可以返回缓存数据,而不是直接失败:

try:
    return await breaker.call(api_call)
except CircuitOpenError:
    # 回退:提供缓存数据
    print("Serving cached data (circuit open)")
    return get_cached_fixtures(league_id)

Azure API Management 在后端资源上提供了 circuitBreaker 属性。你可以分四步进行配置:

  1. 定义后端资源,包括其 URL 和协议。

  2. 添加一条带有 failureConditioncircuitBreaker 规则,例如在 10 秒间隔内累计 1 次失败即触发。

  3. 设置 statusCodeRanges 以捕获特定失败,例如 429 响应。

  4. 设置 tripDuration,并启用 acceptRetryAfter,使熔断器按照后端 retry-after 头中给出的时长保持打开。

这种方式对于 Azure OpenAI 后端尤其有效。429 限流响应会将该后端标记为不健康,在此期间熔断器保持打开。熔断模式能够阻止级联故障,并提升服务稳定性与韧性。将故障后端从池中剔除,可以避免一个“生病”的依赖把原本健康的流量也拖下水。你应当分层部署这些防线:每个请求先经过熔断器,再进入带退避的重试逻辑,最后才真正发起 API 调用。如果熔断器已经打开,就直接跳过调用并快速失败。

在 API 网关中结合速率限制与熔断机制

公平性 vs. 健康性

速率限制与熔断器服务于不同目标。速率限制保障公平性,它将容量在不同客户端之间均衡分配,避免某个用户独占资源。熔断器则关注健康性,它负责发现下游服务的故障并停止继续与其通信。前者通过限流控制需求,后者通过熔断保护稳定性。两者结合,才能形成真正具备韧性的架构。你的 API 网关会在入口先施加速率限制,然后再将调用路由到各个后端对应的熔断器。这种分层方式既能阻止流量过载,也能隔离故障传播。

例如,可以将每个客户端的速率限制设置为每分钟 1000 次调用;而当某个下游服务在短时间内出现一定数量异常时,对应熔断器便会打开,拒绝所有发往该服务的调用。客户端会立刻收到降级响应。两种模式的状态都应保存在 Redis 之类的分布式缓存中。这样即便系统重启,也能保留熔断状态与限流计数器,从而防止恢复期间发生重复事务。

适合搭配使用的模式

你的流量策略应当对每条路由同时使用这两种模式。先定义速率限制,再附加带有回退行为的熔断器。一个平衡良好的流量策略,会为每条路由设置限流规则,并为每个服务配置熔断阈值。在部署前,要用真实使用模式测试每项流量策略。也要将相同的流量策略结构应用到多个端点。统一的流量策略可以对读操作与写操作施加不同保护:对写端点,采用严格限流并搭配快速打开的熔断器;对读端点,则可以放宽限流,但依然保留熔断保护。这样,流量策略就成为韧性设计的核心控制点。你定义的每一项流量策略,都同时覆盖公平性与健康性。一套文档清晰的流量策略,也能帮助团队在事故发生时更快响应。请为每个流量策略端点配置明确、具体的阈值。

只对幂等操作应用重试。GET 调用适合重试;带幂等键的 POST 也适合重试;绝不要重试非幂等写操作。采用指数退避,例如先等 1 秒,再等 2 秒,再等 4 秒,最多尝试三次。熔断器应放在重试循环内部,让每次重试前都先检查熔断器是否处于打开状态。如果在重试过程中熔断器打开,应立刻停止重试并返回回退结果。.NET 中的 Polly 正好提供了这种模式。你可以配置在出现一定数量异常后打开熔断器,并保持打开一段固定时间,同时记录每次状态转换。

当熔断器处于打开状态时,不要继续重试。应快速失败并返回回退响应。比如在金融系统中,如果认证服务失效触发熔断器,网关可以返回带有维护提示的清晰错误码。客户端侧的重试逻辑也能提升韧性。将 DNS TTL 从 600 秒降低到 60 秒,曾改善过恢复时间。熔断模式可以阻止级联故障。这种方式还能让你把请求负载均衡到健康实例上。

生产环境最佳实践

监控、调优与幂等性

无法度量,就无法调优。先建立监控体系,跟踪每个 IP、token 或路由的请求速率。关注带宽尖峰,并分析请求模式,以区分机器人流量与真实用户。大量 404,以及一波波出现的 429 或 503 响应,都是需要调整限流规则的信号。这些指标能帮助你判断 API 限流规则是过紧还是过松。

一开始应当保守设置阈值。可使用基线对比,例如中位数加上两个标准差,并按周回顾规则。再根据实际流量模式,按小时和工作日进行调整。对于异常检测,可以优化 F1-score,在精确率与召回率之间取得平衡;也可以通过 ROC 曲线分析,选择距离左上角最远的阈值点,以在提高真正率的同时尽量降低误报率。

幂等键能让 POST 和 PUT 端点的重试变得安全。当客户端发送两次相同的 key 时,系统只会处理一次请求,这能避免恢复过程中的重复交易。熔断状态与限流计数器都应存储在 Redis 这样的共享缓存中,以保证多实例和重启后的状态一致性。

避免常见陷阱

过于严格的限制会造成真实损害。阈值过低会误伤合法用户,损害转化率;阈值过高又起不到任何过载保护作用。正常的业务流量峰值,例如电商秒杀,可能会被误判为攻击并遭到阻断;而能模拟正常行为的攻击者,则可能绕过防护,形成安全漏洞。

缺少回退机制,会让用户只能面对生硬的原始错误。熔断器打开时,务必始终定义好回退响应。忽视半开状态也是一个常见陷阱。半开状态存在的意义,就是用少量请求探测服务是否恢复;如果跳过这个阶段,熔断器就可能永远无法再次关闭。复杂的速率限制机制本身也会消耗系统资源。设计不佳的限流方案,甚至可能增加系统负担,而不是减轻压力。请在测试环境中验证每一种限流策略,再投入生产。这样,你才能在没有意外的情况下,将请求负载均衡到健康实例。

速率限制与熔断以不同方式保护你的系统。前者守护公平性与容量,限制每个客户端可发送的请求数量;后者守护健康性与恢复能力,在故障扩散前切断对失败服务的调用。两者结合,便能同时覆盖需求侧压力与稳定性风险。先从保守阈值开始,观察监控数据,再根据真实流量模式逐步调整。你的网关位于系统最前端,因此请从今天起就在这里配置好这两种模式。为每一条关键路由都加上限流规则与熔断器。现在多做一点配置,明天就可能少一次宕机。

常见问题

速率限制和熔断有什么区别?

速率限制用于限制客户端在某个时间窗口内可发送的请求数量;熔断则用于停止对故障服务的调用。前者保护公平性与容量,后者保护健康性与恢复能力。你的网关需要两者配合,才能同时应对流量尖峰与服务故障。

我该选择哪种速率限制算法?

令牌桶允许短时突发,同时限制持续滥用;漏桶将流量平滑成稳定输出;固定窗口在离散时间块内计数;滑动窗口跟踪移动时间范围,可避免边界突发。具体应根据你的流量形态以及你对突发流量的容忍度来选择。

熔断器如何决定何时打开?

你需要设置触发阈值,例如在短时间内发生一定数量的超时。一旦故障超过这条线,熔断器就会打开,并保持打开一段时间。之后它会进入半开状态,用少量请求测试服务是否恢复。

熔断器打开时会发生什么?

你的网关会停止向故障服务发送所有调用,并快速失败。它会返回回退响应,而不是原始错误。你可以提供缓存数据,或显示明确的维护提示。这样系统中健康的部分仍能继续工作。

速率限制计数器和熔断状态应该存储在哪里?

应将两者都存储在 Redis 这样的共享缓存中。这样可保证多个网关实例以及系统重启后的计数器与熔断状态一致。如果没有共享状态,每个节点都会单独跟踪自己的限额,客户端就可能突破你原本设定的总上限。

您的免费试用从这里开始!
联系我们的团队申请物理服务器服务!
注册成为会员,尊享专属礼遇!
您的免费试用从这里开始!
联系我们的团队申请物理服务器服务!
注册成为会员,尊享专属礼遇!
Telegram Teams