预算
预算可以在组织、环境、调用方 API Key、服务提供方密钥、团队、成员或成本归属标签级别控制 AI 支出。控制面计入支出,并在预算达到限额时将其标记为已用尽。网关随配置接收这些预算,并在调用上游服务提供方之前自行执行。
预算可通过 AISIX Enterprise 或 AISIX Cloud 使用,不属于 AISIX OSS 资源模型。
前提条件
开始前,请准备以下内容:
- 具备将要创建预算的 AISIX Enterprise 或 AISIX Cloud 组织访问权限。
- 对于模型目录未涵盖的模型,请配置模型定价,以便其流量产生的支出计入预算。
- 对于团队预算,请创建团队,并绑定其流量应计入该预算的调用方 API Key。
- 对于标签预算,请按成本归属标签中的说明声明标签键并设置标 签值。
创建预算
- 打开控制台的 预算 视图,然后选择 新建预算。
- 在 名称 中输入预算名称。
- 选择 范围:组织、环境、调用方 API Key、服务提供方密钥、团队、成员、团队中的每个成员或标签。系统提示时,再选择 环境 或目标。对于标签范围,请选择标签键并填写值。对于调用方 API Key 范围,请先选择 环境,再选择 API Key。
- 在 上限(USD)(人民币组织中为 上限(CNY))中输入限额,并在 周期 中选择日、周或月。预算使用组织币种。
- 在 告警阈值(%) 中输入应发送通知的限额百分比。默认阈值为 80%。详见预算告警与通知。
- 保持选中 达到上限时硬停止,以便达到限额后拒绝匹配的流量。取消选中后,预算将变为仅告警预算,继续放行流量并在控制面中显示超出预算的状态。
- 选择 创建预算。
资源视图还提供内联预算控件作为快捷入口。这些控件位于 API Key 列表、服务提供方密钥列表、成员 视图和团队详情页。团队详情页同时包含共享团队预算和每个成员的预算。内联控件和 预算 视图编辑的是同一个预算,因此在任意一处所做的更改都会同步显示。
一个目标可以拥有一个预算。编辑该预算可以更改限额、周期或执行模式。如果需要控制其他目标,请创建另一个预算。
预算目标
选择能够代表所需控制支出的最细粒度目标:
| 目标 | 计入预算的支出 |
|---|---|
| 组织 | 组织中的所有受管网关流量 |
| 环境 | 某个部署环境中的流量 |
| 调用方 API Key | 使用某个下游应用或租户密钥进行身份认证的流量 |
| 服务提供方密钥 | 使用某个上游凭证或服务提供方账户的模型的平台成本 |
| 团队 | 来自绑定到某个团队的每个调用方 API Key 的流量 |
| 成员 | 在整个组织范围内,来自绑定到某个成员的每个调用方 API Key 的流量 |
| 团队中的每个成员 | 为每个成员通过绑定到某个团队的密钥发送的流量分别设置限额 |
| 标签 | 在组织所有环境中,归属到某个标签值(例如 department=rnd)的流量 |
团队和成员预算取决于调用方 API Key 上存储的身份。一个密钥可以包含团队绑定、成员绑定、两者或都不包含。仅仅是团队成员并不会使该密钥的支出计入团队预算;只有请求所使用密钥上的绑定才能决定适用哪些预算。
服务提供方密钥记账会跟随请求成本被计入时附加到模型的凭证。执行则按请求将要使用的上游判定,而不是按调用方 API Key:
- 如果某个路由目标的模型所用服务提供方密钥上有已用尽的阻断型预算,该目标会被跳过。AISIX 在应用路由 策略和回退上限之前移除它,因此被跳过的目标不会占用回退次数。目标分布在其他服务提供方密钥上的模型组会继续经由它们提供服务。
- 只有当请求可用的所有目标都在已用尽的服务提供方密钥上,或者请求直接调用使用这类服务提供方密钥的模型时,才会以
429和budget_exceeded拒绝。 - 在集成模型中,使用已用尽服务提供方密钥的面板成员视为失败成员,使用这类密钥的裁判模型会使请求失败。
服务提供方密钥预算不适用于 MCP 和 A2A 流量。
成员预算和团队中每个成员的预算会计入不同的流量:
- 成员预算在整个组织范围内生效。它会合并绑定到该成员的每个调用方 API Key 所产生的支出,不受密钥团队绑定的影响。
- 团队中每个成员的预算会为该团队内的每个成员分别设置限额。仅当调用方 API Key 同时包含该团队绑定和成员绑定时,该预算才适用。
标签预算计入解析出的标签包含其 key=value 的每个请求,无论该值来自 JWT Claim、调用方 API Key、其团队还是其成员。详见请求如何解析标签和按标签设置预算。
如果团队或成员预算计入了意外流量,请检查到达网关的调用方 API Key 上的绑定,以及这些绑定是否在当前周期内变更过。绑定变更前已计入的支出仍归属原来的绑定,详见支出如何计入。
示例:一名成员属于两个团队
假设 Alice 同时属于 frontend 和 data 团队,并使用三个调用方 API Key:
| 密钥 | 团队绑定 | 成员绑定 |
|---|---|---|
K1 | frontend | Alice |
K2 | data | Alice |
K3 | 无 | Alice |
该组织配置了以下月度预算:
- Alice 拥有 300 美元的成员预算。由于三个密钥都绑定到 Alice,
K1、K2和K3的支出都会计入这个组织级限额。 frontend团队拥有 1,000 美元的共享预算。绑定到frontend的每个密钥的支出都会计入,包括K1、绑定到其他成员的密钥以及未绑定到任何成员的密钥。frontend中的每个成员拥有 100 美元的限额。只有K1会计入 Alice 的限额,因为它同时包含 Alice 的成员绑定和frontend团队绑定。其他每个成员都会获得独立的 100 美元限额。
通过 K2 发送的流量不会计入任何 frontend 预算。虽然 Alice 属于两个团队,但由于 K3 没有团队绑定,它不会计入团队预算。
通过 K1 发送的请求会检查每个匹配的预算,包括 frontend 团队预算、Alice 的成员预算、她在 frontend 中的成员限额,以及任何匹配的组织、环境或调用方 API Key 预算。任何达到限额的匹配阻断型预算都会拒绝该请求。服务提供方密钥预算则如上所述,按请求将要使用的上游判定。
支出如何计入
控制面以增量方式计入支出。网关上报请求的用量后几秒内,该请求的成本会计入它适用的每个预算,包括匹配的组织、环境、调用方 API Key、服务提供方密钥、团队、成员、团队中每个成员以及标签的预算。
计入的是请求记录的成本,计算方式见模型定价:它已体现模型组价格、价格分档和低峰折扣;由响应缓存应答的请求不计入任何支出。
服务提供方密钥预算例外。它累计的是经该密钥的请求实际花费的成本:每条事件的 upstream_cost,为 null(目标模型没有价格,或事件早于该字段)时回退到 cost。因此模型组价格和低峰折扣不影响它,组价为 0 的请求仍会消耗它。其他范围都累计 cost。由于计入由控制面完成,网关无需为此升级。控制面升级时已计入的支出不会下降,但在使用组价的环境中,服务提供方密钥预算的增速会变化,触达硬限制的时间也可能随之改变。
请求的归属在其成本被计入时确定,依据的是当时生效的绑定:调用方 API Key 的团队和成员绑定、模型的服务提供方密钥,以及环境所属的组织。标签预算例外:它计入网关在请求运行时记录在用量上的标签,因此之后的标签变更不会移动已记录的支出。已计入的支出会留在原归属中。以下变更不会改变当前周期已计入的支出,只有之后的请求才会 按新绑定计入:
- 将调用方 API Key 改绑到其他团队或成员。
- 将模型改到其他服务提供方密钥。
- 删除调用方 API Key、成员、团队或环境。
- 移除超出组织用量数据保留窗口的用量记录。
例如,某个 Key 从 frontend 团队改绑到 data 团队后,它此前请求的支出仍留在 frontend 团队预算中。该 Key 之后的请求会计入 data 团队预算,也不再受 frontend 预算检查。
新预算并不从零开始。创建预算,或更改预算的目标或周期时,预算会以其目标在当前周期内已记录的支出作为起点,并按当前绑定归属;之后再以增量方式计入新的支出。
每个周期都从零开始。属于上一周期、但上报较晚的请求用量不会被计入。
执行路径
配置预算后,应用仍然使用相同的代理 API 和调用方 API Key,无需调用单独的预算 API。
控制面把每个阻断型预算作为配置的一部分,发送给它所适用的每个环境中的网关,并在预算支出达到限额后将其标记为已用尽。仅告警预算不会下发。AISIX 发送服务提供方请求前,网关会检查自己持有的预算,而不会询问控制面,因此没有阻断型预算适用的请求在预算检查上从不依赖控制面。
如果没有匹配的阻断型预算已用尽,请求会继续沿正常代理路径执行。服务提供方响应后,本次请求的用量可能会使预算超出限额。几秒内,控制面会计入这笔支出并把预算标记为已用尽,之后网关会在调用服务提供方前拒绝匹配的流量。把限额调到支出之上、取消选中 达到上限时硬停止 或删除预算,都会以同样的方式解除拦截。
下一个周期开始时,网关也会自行解除已用尽预算的拦截。周期按 UTC 日历划分:日周期从 UTC 00:00 开始,周周期从周一 UTC 00:00 开始,月周期从每月 1 日 UTC 00:00 开始。限额为零的预算在每个周期都会拒绝匹配的流量。
预算拒绝响应
对于 OpenAI 兼容请求,预算拒绝会返回 429 和 OpenAI 风格的错误封装:
{
"error": {
"message": "api key budget 'production-chat' exceeded ($1.00/month). Resets 2026-06-01 00:00 UTC.",
"type": "billing_error",
"code": "budget_exceeded",
"scope": "api_key",
"scope_ref": "api-key-uuid-1",
"limit": "1.00",
"spent": "2.00",
"period": "month",
"period_resets_at": "2026-06-01T00:00:00Z",
"retry_after_seconds": 259200
}
}
金额使用组织币种。message 用该币种的符号书写上限,例如人民币组织中为 ¥1.00;limit 和 spent 以该币种的纯数字表示。1.9.0 及更早版本的网关将这两个字段返回为 limit_usd 和 spent_usd。
Anthropic 兼容的 Messages 请求保持 Anthropic 错误格式,不包含额外的预算字段。
控制面中断期间的行为
预算检查在网关上执行,因此控制面中断不会变成预算拒绝。控制面不可达期间,网关会继续执行它最近一次收到的预算:
- 已用尽的预算继续生效。下一个周期开始时,网关会自行解除拦截,无需等待控制面。
- 未用尽的预算继续放行流量。支出依据网关上报的用量计入,因此网关无法上报用量时,控制面无法把预算标记为已用尽,流量可能超出限额。
- 没有阻断型预算适用的请求不受影响。
预算随网关配置一起下发。中断期间重启、并从配置缓存恢复的网关会继续执行这些预算。
选择预算执行模式
组织的预算执行模式决定网关无法上报用量期间如何处理受预算约束的流量。要更改该模式,请打开 设置,选择 策略 标签页,找到 预算执行 卡片。只有组织所有者和管理员可以更改。
| 模式 | 网关无法上报用量期间的行为 |
|---|---|
| 保持最近状态(推荐) | 默认模式。网关继续按最近一次收到的预算状态执行,如上所述。 |
| 严格 | 网关无法上报用量的时间超过宽限期后,会以 503 和代码 budget_unverified 拒绝有阻断型预算适用的调用方 API Key 的请求,并停止使用所属服务提供方密钥设有阻断型预算的上游。没有阻断型预算适用的请求和上游不受影响。 |
严格模式以可用性换取更严格的支出上限。组织预算或环境预算适用于每个调用方 API Key,因此在严格模式下,宽限期过后它会拒绝所在环境中的全部流量。
在同一卡片的 严格模式宽限期(秒) 中设置宽限期,然后选择 保存。默认值为 600 秒,可接受 60 到 86400 之间的整数。
宽限期从网关有待上报、但无法送达的用量时开始计算。无法建立连接、超时、收到服务器错误或被拒绝授权的上报尝试都不会结束它。第一次到达控制面的上报会结束宽限期,网关随即停止拒绝受预算约束的流量。每个网关分别衡量自己的上报情况,并通过 aisix_usage_delivery_unhealthy_seconds 报告上报已失败的时长。
在严格模式下,已用尽的预算仍以 429 和 budget_exceeded 拒绝。当模型组的所有目标都被排除时,只要其中有目标位于已用尽的服务提供方密钥上,请求就收到 429 budget_exceeded,否则收到 503 budget_unverified。
早期版本提供的失败开放模式已不再可用。使用该模式的组织在控制面升级时已切换为 保持最近状态。
预算用量指标
控制面跟踪受管网关流量的预算用量。当某个预算拒绝调用方 API Key 时,AISIX 会根据该预算的合计值,使用调用方 API Key ID,以及在可用时使用投影的团队和成员 ID 记录预算 Gauge 指标。当该密钥后续的请求未被预算拒绝时,AISIX 会将该密钥身份的 aisix_budget_details_present 设为 0,但保留上次上报的金额。仅在该存在标志为 1 时使用这些金额。aisix_budget_limit、aisix_budget_spent 和 aisix_budget_remaining 这几个 Gauge 取自控制面上报的金额,币种为组织币种。组织切换币种后,同一条序列会以新币种的数值继续。1.9.0 及更早版本的网关将这些 Gauge 导出为 aisix_budget_limit_usd、aisix_budget_spent_usd 和 aisix_budget_remaining_usd。
控制面会把每个已耗尽预算的金额同时写成两套名字:limit、spent、remaining,以及旧的 limit_usd、spent_usd、remaining_usd,让 1.9.0 及更早版本的网关继续读取。因此更新版本的网关会对已耗 尽的预算输出 row loaded with unknown fields ignored 警告,其中列出这三个 *_usd 字段。该警告属于预期行为,无需处理。
验证预算执行
使用与预算目标匹配的调用方 API Key 和模型发送流量。然后在 预算 视图中检查预算,确认支出计入预期范围。
在控制面首次测量某个预算的支出之前,该预算显示 暂无消费数据,而不是 $0.00。新建预算通常在几秒内获得首次测量;控制面升级后,每个预算都要等到下一次测量。调用方 API Key、环境、团队、成员和服务提供方密钥页面上的预算区域同样如此。在 Admin API 中,state.aggregated_at 在首次测量之前为 null,之后记录最近一次测量支出的时间。
使用用量上报确认模型请求产生了支出。如果可以看到 Token 用量,但没有支出,请检查模型定价是否包含与服务提供方和模型名称完全匹配的条目。
仅告警预算在达到限额后仍会继续放行匹配的流量,并在控制面中显示超出预算的状态。阻断型预算会以 429 拒绝后续匹配请求。由于控制面会在服务提供方响应后记录用量,使支出越过限额的请求本身仍可能完成。在网关收到预算已用尽的状态之前几秒内发出的请求也可能完成。
检查预算拒绝
当 AISIX Enterprise 或 AISIX Cloud 部署返回 budget_exceeded 时,请先检查错误码和结构化预算字段。该决定由网关依据控制面最近一次下发的预算状态作出,而不是来自 AISIX Cloud Admin API。
带代码 budget_unverified 的 503 不是支出决定。它表示组织使用严格预算执行,且网关无法上报用量的时间已超过宽限期。请检查网关到控制面的连接及其 aisix_usage_delivery_unhealthy_seconds 指标;参见控制面中断期间的行为。
在 预算 视图中找到返回的目标,并检查其限额、周期和执行模式。如果范围不符合预期,请检查请求所使用调用方 API Key 上的团队和成员绑定。
后续步骤
配置预算告警与通知,在达到所配置的阈值时接收 Webhook 或 Slack 消息。然后使用日志记录与审计调查预算拒绝及其背后的控制面变更。