API 网关专栏 · 第 74 章

电商 API 网关架构:结算可靠性与流量高峰

2026年09月16日
电商 API 网关架构:结算可靠性与流量高峰

电商 API 网关应避免浏览、购物车、库存、结算与合作伙伴 API 共享一个不受控制的故障域。面对流量高峰,目标不是接收所有请求,而是保住价值最高的用户旅程、防止重复状态变更,并确保降级可见且可撤销。

网关可以整形流量并控制发布,却无法创造库存、让非幂等支付自动变得安全,也无法在缺少持久应用状态时恢复已经提交的订单。

核心要点

  • 为浏览、购物车、结算、库存和合作伙伴流量设置独立的容量与故障策略。
  • 把结算幂等性建设成持久应用契约;网关重试策略无法凭空创造幂等性。
  • 在流量高峰前为结算预留容量,再有意识地丢弃低优先级工作。
  • 逐步发布路由与服务变更,但不能假设小时间窗口内的加权流量会产生精确比例。
  • 将网关结果与订单和支付状态关联,同时不要把请求 ID 当作可信身份。

把商店拆分成不同工作负载

工作负载典型特征网关策略重点服务责任
浏览与搜索高流量,以读取为主,部分内容可缓存缓存、宽松限流、优雅降级搜索新鲜度与商品目录正确性
购物车用户状态与频繁写入已认证预算与有界负载购物车一致性与过期
结算几乎不能容忍重复或模糊结果严格准入、不盲目重试 POST、稳定路由幂等性、订单状态机与对账
库存热点 Key 与竞争请求边界与过载信号预留与超卖策略
合作伙伴与 Webhook突发机器流量合作伙伴身份、配额、签名检查事件去重与业务处理

一个全局 RPS 限制无法覆盖这些差异。应分别保护结算并发和下游连接池,避免它们受浏览流量影响。Worker、队列、数据库和支付服务商的预留容量必须与网关预算匹配。

把结算幂等性放在网关之后

1sequenceDiagram
2    participant C as 客户端
3    participant G as API 网关
4    participant O as 订单服务
5    participant D as 持久幂等存储
6    participant P as 支付服务商
7    C->>G: POST 结算、已认证用户与幂等键
8    G->>G: 验证身份、结构、大小与准入预算
9    G->>O: 转发一次有边界的尝试
10    O->>D: 原子占用用户、操作、幂等键与请求指纹
11    alt 已完成的现有幂等键
12        D-->>O: 已存储结果
13        O-->>G: 相同业务结果
14    else 正在处理的现有幂等键
15        D-->>O: 处理中状态
16        O-->>G: 待处理或冲突响应与状态查询
17    else 新幂等键
18        O->>P: 使用服务商幂等键创建或确认支付
19        P-->>O: 服务商结果
20        O->>D: 存储持久订单与结果
21        O-->>G: 业务结果
22    end
23    G-->>C: 响应

RFC 9110规定代理不得自动重试非幂等请求。只有应用已经定义并执行幂等语义,或能够证明原请求没有生效时,结算 POST 才能安全重复。

幂等键应绑定到已认证账户和规范化请求指纹。若同一个键对应不同购物车、金额或币种,应拒绝请求,而不是悄悄返回无关结果。结果的保存时间要覆盖客户端、网关、队列与支付服务商的重试窗口。

构建高峰流量准入计划

应在活动前明确保护顺序:

  1. 尽早拒绝格式错误、负载过大或未认证的工作;
  2. 按客户端和合作伙伴设置预算,避免单一来源耗尽集群;
  3. 依据订单、库存和支付系统容量限制结算并发;
  4. 先于结算功能丢弃推荐、个性化与高成本分析;
  5. 返回明确的过载响应,且只有在恢复时间有意义时才返回 Retry-After;
  6. 下游队列无法在有界时间内排空时,停止接收新工作。

限流不等于容量。还应观测活跃请求、队列年龄、连接池饱和度、依赖延迟与错误类别。等队列已经失控后才触发的自动扩容,并不是完整的高峰计划。

使用受控流量切分发布版本

Apache APISIX 3.19.0 的 traffic-split 插件可以把流量分发到多个加权上游。下面的片段为 checkout v2 分配权重 1,并让路由的基础 v1 上游保留权重 9。这只是配置片段;部署时还要定义两个 Upstream 对象、健康检查、TLS 与回滚自动化。

1{
2  "uri": "/checkout",
3  "methods": ["POST"],
4  "plugins": {
5    "traffic-split": {
6      "rules": [
7        {
8          "weighted_upstreams": [
9            {"upstream_id": "checkout-v2", "weight": 1},
10            {"weight": 9}
11          ]
12        }
13      ]
14    }
15  },
16  "upstream_id": "checkout-v1"
17}

APISIX 文档警告:由于使用加权轮询,实际比例可能不够精确,状态重置后尤其如此。应用足够大的样本评估金丝雀版本,并关注重复尝试、库存冲突、支付拒绝和结算完成率等业务结果,而不是只看 HTTP 错误率。

对会改变状态的流量,不要使用调用方可控请求头选择不受信任的版本。如果需要粘性分配,应从已认证、经过隐私审查的服务端 Key 派生,并验证两个版本共享兼容的订单与幂等状态。

按用户旅程定义降级行为

  • 商品目录不可用:只有价格与库存语义清楚时,才能返回有边界的陈旧数据。
  • 推荐服务不可用:省略推荐模块,不要拖慢结算。
  • 库存缓慢:停止承诺库存,也不要接收无法按策略预留的订单。
  • 支付结果不确定:显示待处理状态并执行对账;不要让客户端盲目重新提交支付。
  • 订单数据库不可用:无法确认持久幂等与提交状态时,拒绝新结算。
  • 遥测不可用:使用有界缓冲;不要把整个请求或支付数据写入应急日志。

熔断器可以减少对故障依赖的重复压力,但熔断打开并不代表业务成功。应为每条路由定义准确的客户端状态和恢复操作。

观测业务边界

Apache APISIX 的 request-id 插件会保留指定请求头中非空的调用方请求 ID;请求头缺失或值为空时才生成新值。因此,该值适合关联,却不是可信身份。若要保留外部 ID,应验证其长度与格式,并与已认证主体分开记录。

记录网关路由、发布版本、准入结果、上游尝试、延迟和响应类别,再与应用拥有的订单、库存和支付引用关联。网关返回 200 不能证明支付已结算,超时也不能证明支付失败。

高峰准备检查清单

  • 浏览、购物车、结算、库存、合作伙伴与 Webhook 预算是否彼此独立?
  • 结算是否执行持久幂等键与请求指纹?
  • 每条非幂等重试路径是否都能解释且有明确边界?
  • 压力测试是否覆盖热门商品、缓慢支付和队列饱和?
  • 低优先级工作是否会在结算容量前被丢弃?
  • 停止金丝雀版本时是否会丢失幂等或订单状态?
  • 依赖故障是否会呈现准确的待处理、重试或不可用状态?
  • 网关证据能否与持久订单和支付记录对账?

常见问题

结算 POST 超时后,网关是否应该重试?

不能盲目重试。只有应用契约已经让操作具备幂等性,并且重试复用同一个幂等键时才可重试;否则应查询或对账现有操作。

浏览与结算是否应该共享一个限流策略?

不应该。它们的价值、成本和故障后果不同,应使用独立的路由、Consumer、并发与依赖预算。

90/10 流量切分是否会精确产生 10% 金丝雀流量?

不会。权重只是分配机制,小样本或状态重置可能产生偏差。应测量实际分布和业务结果。

后续步骤

添加并发预算与背压,定义安全的超时与重试策略,并使用网关 CI/CD 验证与回滚管理变更。

获取方案