跳转到正文
API 网关指南
本文目录

第 96 篇

用 API 网关控制降低云成本:先度量,再优化

当 API 网关能够拒绝不该执行的工作、安全复用缓存响应、限制放大效应,并明确哪些路由和消费者正在制造负载时,它可以减少可避免的云成本。但网关无法自动修复低效应用;仅仅增加一层代理不会降低云账单;只看请求数也无法证明真正节省了成本。

应先定义单位经济性和用户可感知的目标。优化的是每次成功业务操作的成本,而不是每个网关请求的成本。如果一种更便宜的路径增加了错误、陈旧数据或事故处置时间,它就不是优化。

核心要点

  • 在调整策略前,先用有界的路由或产品维度归因请求、字节、延迟和结果。
  • 分开核算网关、网络、计算、托管服务和下游成本,避免一项节省把更大的账单转移到别处。
  • 在无效、滥用或超预算流量消耗昂贵的上游资源前将其拒绝。
  • 只有在身份、授权、新鲜度和失效边界都明确时才缓存响应。
  • 根据实际需求和下游容量扩缩容,不要用增加网关副本代替依赖容量规划。
  • 每次只发布一种成本控制,并用可靠性、安全和业务指标作为护栏。

先定义成本单位

实用的成本单位通常是一次成功业务操作,例如已接受的订单、完成的搜索或生成的报告。可以按一个统计周期计算:

1每次成功操作成本 = 可归因的云成本 / 成功业务操作数

分子可以包含网关计算、负载均衡、跨可用区或公网传输、可观测性、缓存存储、数据库、队列、函数和第三方调用。分母则不能把业务失败但传输层返回成功的请求算进去。

至少需要跟踪以下维度:

维度需要回答的问题常见错误
路由或 API 产品哪个稳定的操作拥有这部分工作?把包含 ID 的原始路径作为标签
消费者类别哪个经过认证的套餐或工作负载类别触发了请求?把调用方提供的请求头当成可信身份
结果操作是成功、被拒绝、被重试,还是结果不明确?把每个 2xx 都当成业务成功
字节有多少数据进入、离开或跨越区域和可用区?只看请求数
依赖调用了哪个上游、队列、函数或供应商?把全部下游成本都归到网关
时间发布、事故或流量迁移是否改变了单位成本?比较条件不同的时间窗口

Apache APISIX 3.19.0 的 prometheus 插件会暴露请求状态、延迟、带宽和上游相关标签。这些信号可用于归因,但金额仍应以账单为准。需要把网关观测数据与云厂商成本导出和应用业务结果进行核对。

优化前先画出成本路径

1flowchart LR
2    C[经过认证的客户端] --> G[API 网关]
3    G -->|已准入工作| U[上游服务]
4    U --> D[数据库 队列 函数或供应商]
5    G -->|安全缓存命中| R[缓存响应]
6    G -->|无效 滥用或超预算| X[有界拒绝]
7    G -. 请求 字节 延迟 结果 .-> M[成本与可靠性模型]
8    U -. 业务结果 .-> M
9    B[云账单导出] -. 实际支出 .-> M
10    M --> P[经过审查的策略变更]
11    P --> G

网关执行经过批准的准入或缓存策略。账单数据只负责报告支出,不负责决定请求授权;应用结果用于证明已接受的工作是否有价值。必须把这些责任分开。

调基础设施前先消除工作量

最便宜的上游调用,是根本不需要发生的调用。建议按以下顺序应用控制:

  1. 清理废弃客户端、路由、轮询和重复调用;
  2. 在转发前拒绝格式错误或未授权的请求;
  3. 限制请求大小、速率、并发、重试和总截止时间;
  4. 缓存可安全复用的响应;
  5. 对真正异步的工作进行批处理或交接;
  6. 最后再为剩余负载调整规格和扩缩容。

不要用限流代替认证或套餐权益判断。计数键必须由服务端根据认证上下文映射。未经验证的 X-Tenant-ID 等请求头会让调用方自行选择另一个租户的预算。

示例:限制并缓存读取路由

下面是一个适用于 APISIX 3.19.0 的可运行形态 Route 请求体。它假设已经存在 catalog-v1 Upstream 和 memory_cache 区域。缓存只保存成功的 GET 和 HEAD 响应 30 秒;生产使用前仍需证明这些响应可安全复用。

1{
2  "uri": "/catalog/*",
3  "plugins": {
4    "limit-count": {
5      "count": 1000,
6      "time_window": 60,
7      "key_type": "constant",
8      "key": "catalog-read",
9      "rejected_code": 429,
10      "allow_degradation": false,
11      "show_limit_quota_header": true
12    },
13    "proxy-cache": {
14      "cache_strategy": "memory",
15      "cache_zone": "memory_cache",
16      "cache_method": ["GET", "HEAD"],
17      "cache_http_status": [200],
18      "cache_ttl": 30,
19      "cache_control": false,
20      "hide_cache_headers": false,
21      "consumer_isolation": true,
22      "cache_set_cookie": false
23    }
24  },
25  "upstream_id": "catalog-v1"
26}

设置 cache_control: false 后,内存缓存使用配置的 30 秒 TTL,同时仍会拒绝缓存上游标记为 private、no-store 或 no-cache 的响应。这个常量计数器是路由级容量护栏,不是单用户权益。使用默认本地计数策略时,每个 APISIX 实例维护自己的计数,因此总配额会大致随实例数增长。如果需要整个集群共享一个配额,就必须有意识地设计共享计数策略。

相关行为布尔参数的两条路径如下:

参数默认值true 路径false 路径与信任边界
limit-count.allow_degradationfalse计数后端失败或动态限制值无效时绕过限流失败返回 500;示例保留此路径,避免控制失效后悄悄放开无界成本
limit-count.show_limit_quota_headertrue返回配额请求头隐藏配额请求头,但不会关闭限流
proxy-cache.cache_controlfalse对内存缓存应用请求侧 Cache-Control 语义和 TTL 推导不应用这些请求侧语义;两条路径都会遵守上游的 private、no-store 和 no-cache,不缓存相应响应
proxy-cache.hide_cache_headersfalse对客户端隐藏 Expires 和 Cache-Control保留这些响应头
proxy-cache.consumer_isolationtrue按已解析的 APISIX Consumer 或远程用户划分有效缓存键,除非键本身已包含身份在消费者间共享缓存;只有授权和响应内容确实完全相同时才安全
proxy-cache.cache_set_cookiefalse内存缓存可以保存带 Set-Cookie 的响应不缓存这类响应;磁盘缓存不会接受 true 覆盖

只有认证链路真正建立了 APISIX Consumer 或远程用户值时,这些值才有意义。缓存不能从任意调用方请求头推断身份。APISIX proxy-cache 文档还说明两种策略都会遵守 Vary;应根据应用契约验证完整缓存键、授权行为和失效路径。

验证缓存是否安全地省钱

衡量缓存命中率时,还要同时观察:

  • 减少了多少源站请求和计算时间;
  • 增加了多少网关内存或磁盘成本;
  • 响应年龄和失效延迟;
  • 跨可用区和公网字节;
  • 授权与数据隔离测试;
  • 陈旧、缺失和错误响应比例;
  • p50、p95 和 p99 客户端延迟。

如果缓存键遗漏了语言区域、授权范围、编码或其他表示维度,即使命中率很高也可能不安全。不要为了改善图表而缓存个性化、频繁变更或具有副作用的响应。

控制重试和扇出放大

一个客户端请求可能触发多次网关尝试、服务调用、队列消息、数据库查询和供应商调用。应分别记录客户端请求数和上游尝试数。把总重试预算放在调用方截止时间内,只对已经证明可安全重放的操作重试。

扇出也需要独立预算。一个会调用 20 个服务的搜索接口,成本可能高于 20 个简单接口,尽管网关只看到一个请求。内部工作由应用或编排层负责;网关可以限制输入和时间,却无法推断正确的扇出计划。

约束需求后再调整规格

自动扩缩容是在观察到信号后才调整容量。它不会增加数据库连接、第三方配额或区域网络容量。应使用负载测试得到的容量边界,保留最低热容量,并依据具有前瞻性的需求或饱和度信号扩缩容。

需要测量减少网关副本是否增加了长尾延迟、错误率、连接抖动或事故风险。安全缩容需要排空连接和经过测试的终止预算。具体机制可参考弹性扩展 API 网关。

把成本变更当作实验

每项变更都应记录:

  • 假设和预期影响的成本项;
  • 受影响的路由与消费者类别;
  • 基线周期和比较窗口;
  • 可靠性、安全和业务护栏;
  • 回滚触发条件与负责人;
  • 缓存抖动或数据传输账单等滞后影响;
  • 带不确定性的实际单位成本变化。

只有当单位成本确实下降且没有破坏护栏时才推广。供应商折扣、无关流量变化或成功量下降,都可能让总支出降低,却让架构变得更差。

云成本检查清单

  • 成本单位是否是一次成功业务操作,而不是一次请求?
  • 是否分开核算网关、网络、计算、托管服务和下游成本?
  • 每个成本标签是否使用有界且由服务端控制的维度?
  • 无效和未授权请求是否在昂贵工作前被拒绝?
  • 是否把重试尝试和扇出与客户端请求分开观察?
  • 每个缓存键是否包含所有授权与表示维度?
  • 是否审查了所有缓存布尔参数、默认值和两条路径?
  • 调整规格后,热容量是否仍能承受突发和依赖限制?
  • 每项优化是否有可靠性、安全和业务回滚护栏?
  • 声称的节省是否与账单导出核对,而非只从流量推断?

常见问题

增加 API 网关会自动降低云成本吗?

不会。网关本身也有计算和运维成本。只有当共享控制减少的浪费或风险超过新增成本时,它才有价值。

所有读取 API 都应该在网关缓存吗?

不应该。只有在新鲜度、身份、授权、缓存键变化、失效和故障行为都明确且经过测试时才缓存。

限流能执行云预算吗?

它可以限制一个已度量的请求维度,但不能代替账单核对、账户级供应商限制或理解业务语义的成本控制。

后续步骤

先在 API 网关定价与成本优化中建立财务模型,再与弹性扩缩容联动,并使用网关日志分析检查路由结果。

编辑本篇文章

获取方案