API7 网关 3.10.8:让限流决策有据可查

更新时间 10/12/2026

核心要点

  • API7 网关 3.10.8 发布于 2026 年 10 月 9 日,让分布式 API 与 AI 流量的限流依据更加清晰。
  • AI Rate Limiting 的 cost_expr 可以读取 input_tokens_details__cached_tokens 等嵌套数值型 usage 字段;这类拼接字段名需要 3.10.8 数据面,旧实例会把它们计为 0。
  • 对于 Limit Count、Limit Count Advanced、GraphQL Limit Count 和 AI Rate Limiting,$rate_limiting_info 现在以 JSON 形式记录窗口、计数器、增量、决策、滑动窗口和延迟同步上下文。计数器更新失败时,decision 会记为 error,不再伪装成拒绝决策。
  • 3.10.8 修复了 Limit Count、Limit Count Advanced 和 GraphQL Limit Count 的一个延迟同步问题:只处理被拒请求的实例,不会再因为 sync_interval 而持续依据过期的缓存配额拒绝请求。
  • Redis TLS 连接现在会通过 redis_server_name 或主机名形式的 redis_host 发送服务器名称,帮助插件连接按名称路由 TLS 的托管 Redis 服务。
  • 不同 Worker 与网关节点之间的延迟同步仍然是近似计量;来自响应的 AI usage 仍在响应交付后提交,只影响后续决策。本版本提高了正确性与可解释性,但没有消除这些边界。

限流规则很容易被描述成一个数字:每分钟 1,000 个请求、每个订阅 500 个模型 Token,或最多 100 个并发连接。生产环境中的真实决策却复杂得多:它可能依赖本地快照、Redis 共享计数器、滑动窗口估算,或只有在大模型完成响应后才会出现的 usage 数据。

运维人员看到 HTTP 429 时,需要的信息不只是状态码。决策使用了哪个窗口?本次请求让计数器增加了 1,还是消耗了 200 个 Token?这是策略拒绝,还是计数器后端发生了故障?如果某个网关实例只收到被拒请求,它是在刷新共享状态,还是不断延续旧决策?

API7 网关 3.10.8 正面处理了这道运维难题:改进嵌套 AI usage 的计量方式,扩展决策遥测,修复 Limit Count、Limit Count Advanced 和 GraphQL Limit Count 在延迟同步下的过期状态问题,并发送许多托管 Redis 服务所需的 TLS 服务器名称。它并不保证每种模式下的限流都达到数学意义上的完全精确,而是在配置、运行时决策与验证证据之间建立了更清晰的契约。

1flowchart LR
2    request[当前请求] --> decision[响应前配额决策]
3    decision -->|放行| upstream[上游或模型]
4    decision -->|拒绝| reject[策略响应]
5    decision --> evidence[JSON 决策证据]
6    upstream --> response[响应已交付]
7    response -. 在日志阶段提交 usage .-> counter[更新后的计数器]
8    counter --> later[后续请求]

图中的虚线路径非常重要:来自响应的 AI usage 会在当前响应之后更新计数器。它可以影响后续请求,但不会回过头阻断已经产生 usage 的这次响应。

HTTP 429 是结果,不是解释

分布式限流包含多个问题,而监控看板往往把它们压缩成同一条曲线:

  1. 限流键是什么? 配额可能属于消费者、订阅、路由、客户端地址或其它配置值。
  2. 计量成本是多少? 一次请求可以计为 1,也可以按 GraphQL 查询成本或 AI 提供方返回的 usage 计量。
  3. 状态存在哪里? 计数器可以位于本地,也可以通过 Redis、Redis Cluster 或 Redis Sentinel 共享。
  4. 状态何时同步? 直接同步会按请求读写共享状态;延迟同步则先在本地累积增量。
  5. 实际发生了什么? 策略可以放行或拒绝请求,而计数器更新本身也可能成功或失败。

事件排查时,最后一项区别尤其关键。拒绝是基于现有状态作出的策略决策;计数器更新错误则表示网关未能完成部分计量路径。日志不应把两者记录成同一类事件,而且任何一个标签都无法单独说明特定插件配置下的全部客户端行为。

API7 网关 3.10.8 提供了足够的结构化上下文,帮助运维人员把这些问题分开判断。

计量嵌套 AI Usage,但不要假装预知未来

越来越多 AI 提供方会把 usage 组织成嵌套对象。例如,OpenAI Responses API 会把缓存输入 Token 数放在 input_tokens_details 下的 cached_tokens 字段中。在 3.10.8 中,AI Rate Limiting 可以在 cost_expr 中通过以下名称读取这个数值:

1input_tokens_details__cached_tokens

顶层 usage 字段继续使用原有名称,现有表达式无需修改。不过,拼接字段名属于数据面能力。低于 3.10.8 的数据面会把它计为 0,因此新旧版本并存的网关组可能低估表达式原本希望计入的成本。

不要在只升级控制面后就立即把嵌套字段加入生产策略。应等待所有可能处理该路由的数据面都升级到 3.10.8,再发送包含该字段的提供方响应,并验证最终提交的成本。组合字段前还要确认提供方的语义:嵌套的缓存 Token 数可能已经包含在顶层总数中,而不是一项需要额外相加的用量。

计量时机并未改变。当前 AI Rate Limiting 文档说明,响应 usage 在请求准入时尚不可用,因此会在日志阶段提交。第一次成功响应展示的配额可能尚未扣除自身 usage,后续请求才会看到更新后的计数器。

这属于响应交付后的计量,而不是请求前的成本预测。它适合控制一段时间内的累计消耗;对于必须在模型完成响应前限制的风险,仍应单独设置请求体大小、并发或上游保护措施。

让决策证据可由机器解析

在 Limit Count、Limit Count Advanced、GraphQL Limit Count 和 AI Rate Limiting 中,$rate_limiting_info 变量现在会描述请求被计入的窗口。根据所选算法与同步模式,其 JSON 可以包含:

  • 窗口类型与大小;
  • 请求是被放行还是被拒绝;
  • 本次请求给计数器增加的数值;
  • 当前窗口的开始时间、结束时间与计数;
  • 滑动窗口使用的加权上一窗口;
  • 延迟同步决策所依据的快照。

计数器无法更新时——例如 Redis 不可达——该变量会把 decision 记为 error,而不是让事件看起来像策略拒绝。限流键中含有引号或反斜杠时,现在也会正确转义为合法 JSON。

这些改进也要求日志处理流程同步调整。字段顺序不再固定,未来版本还可能加入更多字段。应把变量值作为 JSON 解析,并按字段名取值。继续假设旧序列化顺序的解析器,即使面对完全合法的 JSON,也可能悄悄把新字段解释成错误含义。

应把 decision: error 视为需要排查的信号,而不是客户端响应的完整结论。请结合插件、策略、网关日志、Redis 健康状态与客户端实际状态码进行关联分析。这个变量描述限流状态,但不能替代端到端请求遥测。

延迟同步仍以部分精确性换取更少的 Redis 往返

默认情况下,基于 Redis 的 limit-count 策略会按请求同步。运维人员可以设置 sync_interval,先在本地累积增量,再按间隔写入 Redis。当前文档要求该值不小于 0.1 秒,并且小于数值型 time_window;默认值 -1 表示继续使用直接同步。

这种取舍是有意为之。本地增量完成同步前,不同 Worker 或网关节点可能看到不同的共享计数器状态。在这段间隔内,并发请求可能超过配置数量。如果跨节点精确执行比减少 Redis 往返更重要,就应使用直接同步。

对于 Limit Count、Limit Count Advanced 和 GraphQL Limit Count,API7 网关 3.10.8 修复了这种近似模式中的另一个正确性问题。配置 sync_interval 后,只处理被拒请求的实例可能在本地计数过期时停止刷新缓存配额,并一直依据过期状态拒绝请求,直到缓存配额本身过期。使用滑动窗口时,它还可能在窗口剩余时间内继续套用上一窗口的权重,导致放行量远低于配置限额。Redis 不可达时,同一路径还可能在每次同步时给本地回退计数器计数,尽管实例没有放行任何请求。

本次修复消除了这些过期拒绝与回退计数器问题,但不会让延迟同步变得完全精确,也不会立即合并所有仍在途的本地增量,更不能取代对所选 Redis 策略故障行为的测试。

向托管 Redis 发送它需要的 TLS 名称

只有每个网关实例都能连接到同一个目标后端,基于 Redis 的限流才有意义。在 3.10.8 中,Limit Count、Limit Count Advanced、GraphQL Limit Count、Limit Conn、Limit Req、AI Rate Limiting 与 AI Cache 使用的 TLS 连接会通过 SNI 发送服务器名称。

名称选择规则十分明确:

  • 设置了 redis_server_name 时,网关发送该值;
  • 否则,如果 redis_host 是主机名,就发送这个主机名;
  • 如果 redis_host 是 IP 地址且没有设置显式名称,则不发送服务器名称。

旧版本不会发送任何服务器名称。因此,即使启用了 redis_ssl,按主机名选择 TLS 端点或证书的托管 Redis 服务也可能无法连接。

SNI 只是在 TLS 握手期间传达客户端希望连接的服务器名称,本身并不能证明证书校验或授权已经完成。应测试插件实际使用的完整 Redis TLS 配置,包括名称解析、信任材料、凭据,以及端点不可用时的行为。

故障路径发生了哪些变化

验证限流器最有效的方法,是覆盖正常路径之外的情形。API7 网关 3.10.8 改变了多项故障观测,但没有把它们合并成一种通用行为:

  • Limit Count、Limit Count Advanced、GraphQL Limit Count 和 AI Rate Limiting 中的计数器更新失败:$rate_limiting_info 使用 decision: error,把后端或计量故障与策略拒绝区分开来。
  • **Limit Count、Limit Count Advanced 和 GraphQL Limit Count 在延迟同步下只有被拒流量:**实例会刷新相关共享状态,而不是继续延长过期拒绝行为。
  • **上述三个插件的滑动窗口:**在受影响路径中,过期的上一窗口权重不会继续作用到当前窗口结束。
  • **上述三个插件在延迟同步时 Redis 不可达:**没有放行请求的实例,不会再在同步时反复给本地回退计数器计数。
  • **旧数据面上的嵌套 AI usage:**拼接字段仍会被计为 0;在滚动升级完成前,新旧版本并存仍存在少计风险。

以上内容都不表示所有 Redis 故障必须采用失败放行或失败关闭策略。实际结果取决于使用的插件和配置路径。应测试精确的部署策略,并同时记录客户端响应与结构化决策证据。

升级到 3.10.8 前应验证什么

请结合 API7 网关升级指南与滚动升级流程:先在生产负载均衡器之外部署一个目标版本的数据面作为金丝雀,验证通过后再开始正式滚动升级。

  1. 按变更范围盘点配置:Redis SNI 涉及 Limit Count、Limit Count Advanced、GraphQL Limit Count、Limit Conn、Limit Req、AI Rate Limiting 和 AI Cache;$rate_limiting_info 涉及 Limit Count、Limit Count Advanced、GraphQL Limit Count 和 AI Rate Limiting;延迟同步修复涉及 Limit Count、Limit Count Advanced 和 GraphQL Limit Count。记录相应的 policy、窗口类型、sync_interval、Redis 端点、TLS 选项和日志消费者。
  2. 对于四个支持 $rate_limiting_info 的插件,在数据面滚动升级前把日志处理流程改为按字段名解析 JSON。保留未知字段,不要因为新增字段而丢弃整条记录。
  3. 对于这四个插件,在各自适用的直接同步与延迟同步模式下采集放行、拒绝和 Redis 不可达场景。对比客户端状态、网关日志、decision、增量、窗口边界和计数值。
  4. 使用 Limit Count、Limit Count Advanced 或 GraphQL Limit Count 构造让某个实例主要收到被拒请求的流量,验证缓存配额会正常刷新;对于滑动窗口,还要验证上一窗口权重会随窗口推进而变化。
  5. 如果 Redis TLS 使用托管主机名,应分别测试显式 redis_server_name 与主机名回退。不要假设 IP 地址会提供 SNI。
  6. 在所有相关数据面升级到 3.10.8 前,不要把嵌套 AI cost_expr 字段写入共享配置。升级完成后,再验证提供方响应结构与响应后提交的成本。
  7. 对比第一次成功 AI 响应与下一次请求,让团队理解日志阶段计量的延迟,不要把当前响应头误读为已包含本次最终 usage。
  8. 为 decision: error 与策略拒绝分别设置告警,并在同一排查视图中关联 Redis 健康状态与网关错误日志。

升级期间不要修改网关配置。应备份数据库与声明式配置,在预发布环境验证相同路径,先升级控制面,再按照文档流程滚动升级数据面节点。

让每一次限流都有据可查

API7 网关 3.10.8 没有消除分布式限流背后的取舍。延迟同步仍以短时间内的部分精确性换取更少的 Redis 往返;响应中的 AI usage 仍然来得太晚,无法在响应交付前约束同一次请求;SNI 告诉 Redis 客户端希望连接的服务器名称,却不能描述完整的 TLS 信任决策。

本版本真正改变的是计量契约的质量:嵌套 usage 可以被准确命名。对于 Limit Count、Limit Count Advanced、GraphQL Limit Count 和 AI Rate Limiting,$rate_limiting_info 包含运维人员所需的窗口与计数器上下文,并把计数器更新失败记录为 decision: error。对于 Limit Count、Limit Count Advanced 和 GraphQL Limit Count,只处理被拒流量的实例不会再在受影响的延迟同步路径中继续延长过期状态。

请阅读完整的 API7 网关 3.10.8 更新日志,再把每个限流器拆成输入、状态变化、决策与证据逐项验证。只有当团队不仅知道限流发生过,还能解释它为什么发生,这项策略才真正具备生产可用性。

获取方案