先把“免费”拆成四个不同问题
NodeLoc 上有一类帖子很容易获得关注:发布一个可以调用多个模型的地址,附带一个共享 Token,宣称每天有大量调用次数,甚至可以“无限”使用。S10 的描述还提到,公开 Key 曾经因为滥用而更换,公共入口可能遇到每分钟 60 次的请求墙,而自行创建的 Key 相对稳定。这些细节说明,所谓“免费”并不是一个稳定的服务等级,而是四个不同问题的叠加:谁承担上游额度、谁持有凭证、谁负责限制并发、谁处理滥用后的恢复。
这类服务最容易被误解的地方,是把“当前请求成功”当成“系统可用”。一次成功只能证明上游在这一刻接受了请求,不能证明 Token 还能持续使用,也不能证明响应内容没有被中间人记录,更不能证明所有用户共享同一份配额时仍然公平。
因此,工程上应当把可用性拆开观察:
- 认证可用性:凭证是否有效,是否被撤销或触发风控。
- 配额可用性:账户剩余额度是否足够,公共额度是否被其他用户消耗。
- 调度可用性:入口是否有并发、队列和超时控制。
- 内容可用性:模型是否真的返回了完整响应,而不是错误信息、截断结果或伪造的成功 JSON。
Fastly 官方材料把边缘平台描述为同时提供交付、安全、可编程控制和可观测能力的平台,而不是单纯的 DNS 或缓存服务。这个视角同样适用于 AI API:入口层的价值不在于隐藏一个 Base URL,而在于把凭证、流量和失败状态纳入可验证的控制面。
共享凭证的失效链路
一个公开 Token 通常经过下面的链路失效:
帖子传播 -> 请求量突然增长 -> 公共 Key 触发上游 RPM/TPM 限制 -> 用户重试和并发重放 -> 网关与上游压力继续增加 -> Key 被风控、撤销或额度耗尽 -> 入口返回 401、429、5xx 或“成功但无内容”这里最危险的不是单次超限,而是错误重试形成的放大效应。假设一个客户端在收到 429 后立即重试三次,入口有 100 个并发请求,那么上游看到的可能不是 100 次请求,而是接近 400 次。若每次请求还携带较长上下文,TPM 可能先于 RPM 耗尽;反过来,短请求也可能先撞上每分钟请求数限制。
共享 Token 还会破坏归因。上游只能看到同一个凭证,无法区分正常用户、脚本爬取、批量转发和恶意探测。入口如果也没有记录请求主体、模型、令牌数量和结果状态,就无法回答三个基本问题:是谁消耗了配额、哪一种请求最昂贵、故障是上游拒绝还是入口自身丢包。
一个更可靠的边界是:公开入口可以公开,但上游凭证不能成为公共资源。客户端拿到的应是入口签发的短期身份或受限访问令牌,入口再使用服务端保存的上游凭证访问模型。这样做不能消除额度耗尽,却可以把泄露范围从“任何人都能直接调用上游”缩小到“某个入口身份在某段时间内可调用某些能力”。
一个最小可治理网关
下面的配置不是某一家云厂商的专用格式,而是一份实现检查清单。无论使用反向代理、边缘函数还是自建服务,都应当能明确回答这些字段如何实现。
1. 请求身份与额度隔离
upstream: base_url: ${MODEL_BASE_URL} api_key: ${MODEL_API_KEY}
client_policy: token_ttl: 15m max_requests_per_minute: 20 max_tokens_per_minute: 40000 allowed_models: - model-a - model-b
request_policy: max_body_bytes: 1048576 connect_timeout: 3s response_timeout: 90s max_retries: 1 retry_statuses: [429, 502, 503, 504]MODEL_API_KEY 只能出现在服务端运行环境,不能写入前端 JavaScript、公开仓库、日志或错误响应。客户端令牌应当具备过期时间、作用域和撤销能力。即使系统暂时只服务少量用户,也不要把永久共享 Key 当成身份系统的替代品。
2. 将限流放在重试之前
限流至少要有两层:单客户端限流和全局上游预算。前者防止某个用户独占资源,后者防止所有用户合计突破上游配额。实现上可以使用令牌桶,但必须明确桶容量和补充速率;只写“开启限流”而没有数值,无法验证行为。
伪代码可以表达出关键顺序:
if !client_bucket.allow(request.cost): return 429 with Retry-After
if !global_budget.reserve(request.estimated_tokens): return 503 with quota-exhausted
response = call_upstream(request, retry_once_only)reconcile_budget(response.actual_tokens)return response这里的 request.cost 不应只按请求次数计算。聊天接口的成本通常与输入上下文和输出上限有关,因此可以使用估算 Token 数作为预算单位。估算不准确时,仍要在响应完成后根据上游返回的用量字段校正账本;如果上游不提供用量字段,就必须把预算视为保守上限,而不能假装知道真实消耗。
3. 对错误做分类,不要全部重试
401、403 通常代表凭证或权限问题,继续重试只会放大故障;429 可能是瞬时限流,也可能是日配额耗尽,应该结合 Retry-After、上游错误码和本地预算判断;502、503、504 才更接近可恢复的传输或服务异常。对于流式响应,连接已经发送部分内容后再重试,会造成重复输出,客户端必须具备请求去重或明确提示用户重新生成。
推荐把外部响应映射为稳定的内部错误:
{ "error": { "type": "rate_limit", "message": "请求过于频繁,请稍后重试", "retry_after": 12, "request_id": "req_20261002_0001" }}不要把上游完整错误文本、请求头或凭证片段原样返回给客户端。错误信息需要足够定位问题,但不应扩大敏感信息的暴露面。
可复现的验证方法
没有观测数据时,“这个公益 API 很稳定”只是印象。验证共享 API,重点不是制造压力,而是确认限制和失败边界是否按预期工作。应使用自己的测试账号、低并发和明确的停止条件。
检查认证与响应一致性
curl -sS -D /tmp/headers.txt \ -H "Authorization: Bearer $CLIENT_TOKEN" \ -H 'Content-Type: application/json' \ --data '{"model":"model-a","messages":[{"role":"user","content":"ping"}],"max_tokens":8}' \ https://api.example.test/v1/chat/completions \ -o /tmp/response.json
sed -n '1,30p' /tmp/headers.txtjq '{id, model, choices: (.choices | length), usage}' /tmp/response.json至少记录 HTTP 状态码、请求 ID、模型名、响应耗时、是否流式、输入输出用量和错误类型。不要把完整提示词和完整响应作为默认日志;需要排查内容问题时,应采用脱敏摘要或经过授权的采样。
验证限流是否真的生效
for i in $(seq 1 25); do curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' \ -H "Authorization: Bearer $CLIENT_TOKEN" \ -H 'Content-Type: application/json' \ --data '{"model":"model-a","messages":[{"role":"user","content":"limit-test"}],"max_tokens":4}' \ https://api.example.test/v1/chat/completions sleep 0.2done测试结果不应只看“有没有 200”。如果策略设定为每分钟 20 次,应检查超过阈值后是否返回 429、是否存在 Retry-After、是否仍然消耗上游预算,以及等待窗口结束后是否能恢复。若所有请求都返回 200,但后台没有预算账本,这通常不是“无限”,而是系统尚未暴露它的限制。
验证故障恢复
应至少构造三类受控故障:让测试凭证失效、让上游返回 429、让连接在流式响应中断开。检查清单包括:
- 失效凭证是否在一次失败后进入熔断,而不是持续重试。
- 上游 429 是否遵守等待时间,是否阻止同一客户端继续抢占配额。
- 流式中断后是否出现重复计费、重复消息或客户端无限等待。
- 网关重启后,限流计数和撤销列表是否按设计保留或清空。
- 监控是否能区分入口 5xx、上游 5xx、认证失败和预算耗尽。
工程取舍:透明度比“无限”更重要
共享 AI 服务很难同时满足低门槛、无限额度、匿名访问和长期稳定四个目标。更现实的设计是主动牺牲其中一部分:限制模型范围,限制上下文长度,限制每个身份的预算,并公开当前状态和错误语义。用户不一定需要一个永远成功的入口,但需要知道失败是因为自己的频率、公共预算、上游凭证,还是服务端故障。
多入口或多供应商也不能自动解决问题。Fastly 的官方材料强调可编程控制和可观测能力,Gcore 官方页面则把 CDN、DNS、边缘计算和多 CDN 韧性列为不同能力。把多个上游简单堆在一起,只会增加路由和计费的不确定性;只有当每个上游都有独立健康检查、预算、熔断和回滚条件时,故障转移才是工程能力,而不是换一个 Base URL。
我的结论是:共享 Token 的核心风险不是“免费会不会结束”,而是系统是否具备可归因、可限流、可撤销、可验证的边界。 一个短期可用但完全没有这些边界的公开 Key,本质上是一次性的公共凭证;一个有明确额度、身份隔离和错误契约的 API,即使每天只有有限调用次数,也更接近真正可依赖的服务。
当你下次看到“无限模型调用”时,先不要问它支持多少模型。先检查四件事:凭证是否属于你、请求是否可被单独限流、失败是否能被解释、撤销后是否能安全恢复。答案越模糊,所谓的免费额度就越像一场没有监控的共享实验。
参考资料
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时