TokenPAPATokenPAPA
使用指南API 参考AI 应用博客定价注册

我们如何每天路由 100 万+ 次 API 调用、横跨 60 个模型

统一 AI 网关背后的工程实践:渠道注册表、健康检查与故障转移、负载策略、缓存、限流与可观测性,如何稳定支撑每天 100 万+ 次调用。

我们如何每天路由 100 万+ 次 API 调用、横跨 60 个模型

统一 AI API 的正面很简单:一个 Key、一个 base_url、一份价目表、一个余额。而这张脸背后全是难活。

tokenpapa.ai/v1 这个端点背后调用的不是一个模型。它要扇出到十几个相互独立厂商的 65 个在线模型 ID,每一家都有自己的鉴权方式、自己的限流模型、自己对「一个 token 是什么」的定义、自己的报错词汇表,以及自己会出故障的下午。网关的职责,就是让这一堆东西表现得像一个稳定可依赖的服务。

这是一篇讲设计的文章,不是战绩汇报。下面按层拆解一个高并发统一网关需要什么,以及每一层究竟在吸收哪种故障。

维度实际意味着什么
暴露的模型 ID65 个在线 ID,覆盖 DeepSeek、OpenAI、Anthropic、Google、阿里、月之暗面、智谱、MiniMax、腾讯、字节与小米
客户端界面一个 OpenAI 兼容端点:https://tokenpapa.ai/v1
流量形态突发、流式与非流式混合,各模型之间极不均衡
故障域任意单个上游都可能变慢、被限流、改价或直接消失
计费单位按 token、按模型,缓存命中单独计价
最危险的 bug 类型静默的错误路由——它表现为账单不对,而不是堆栈报错

核心洞察:在规模化之后,网关的职责不是转发请求,而是让几十个异构、各自独立会挂的上游,看起来像一个端点、一份价目表、一套可预期的错误契约。


把问题说清楚

服务一个模型是写个代理。服务 60 个,是调度问题加上「事实一致性」问题。

有四条性质让 LLM 路由区别于普通 HTTP 流量路由:

  1. 单次请求成本不是常数。 打向同一个模型的两个请求,成本可能差三个数量级,取决于输入长度以及模型决定生成多少输出。路由决策就是定价决策。
  2. 故障是部分的。 上游可能完成连接、返回 HTTP 200,然后一个 token 都不吐;也可能吐了半句话就卡住。只看状态码远远不够。
  3. 流式是默认形态。 生产流量大多走 SSE,因此失败可能出现在一段 900 token 回答的第 40 个 token 上。
  4. 消耗的单位是 token,不是调用。 限流、配额和计费全部建立在只有响应结束后才确知的 token 数上。

下面每一层,都是为了吸收上面四条中的某一条。


第一层:渠道注册表

一个渠道就是一份上游凭据,指向一个模型。同一个模型 ID 通常配有多个渠道,而且是刻意为之:两条来自不同通道的 DeepSeek V4 Flash 渠道不会在同一时刻故障,它们的延迟和实际单价也不同。

注册表是路由的唯一事实来源。每个渠道携带这些字段:

字段用途
可服务的模型 ID把请求里的 model= 映射到候选渠道
厂商与区域用于策略分组和延迟假设
权重与优先级控制同一模型内部的流量切分
并发与 token 上限本地上游配额视图
价格覆盖分渠道的输入、输出与缓存单价
健康状态实时状态:健康、降级、冷却、禁用
成本档位调用方要求「优先省钱」时使用

注册表每个请求都要读,但极少写。这种读写不对称就是整个设计的约束条件:读取必须是一次内存查表,不能是一次数据库查询,否则网关会给它服务的每一次调用都加上延迟。

关键结论:路由表是配置,但它以请求速率被读取。把它放在内存里、做版本管理,并把每次写入当成热重载而不是一次数据迁移。


第二层:健康检查、熔断与故障转移

朴素做法是「返回 5xx 就把渠道标记为不可用」,它在三个关键场景下全部失效:返回 200 却卡住的上游、只是慢而不是坏的上游,以及只对某个模型出故障的上游。

可用性够强的健康模型要看四个信号:

  • 存活探测。 每个渠道一个低成本定时探针,并且限定在该渠道服务的模型上。
  • 来自真实流量的被动健康。 用生产请求而不是探针来计算滚动成功率、首 token 时间和卡死率。
  • 熔断。 连续失败达到阈值后把渠道冷却——先从轮转中摘除一个短窗口,再以很小比例的流量试放,确认后才完全恢复。
  • 错误分类。 并非所有 4xx 都是渠道的错。请求格式错误绝不应该触发熔断;401、连续的 429、反复的 5xx 才应该。

故障转移随后分成两种情况,而把它们混为一谈是经典错误:

失败位置正确行为原因
首个 token 到达客户端之前在同一模型的第二个健康渠道上重试调用方除了多花一点延迟,观察不到区别
已经开始流式输出之后关闭流、上报失败,交给客户端决定中途悄悄切换上游会产出拼接感明显的回答
上游返回 200 但内容为空当作失败处理,重试一次后上报「200 但什么都没有」是最常见的静默故障
上游限流(429)改走其他渠道,而不是立刻退避重试在已经打满的同一渠道上重试是最差的选择

第三行才是真正消耗团队排障时间的那一行。一个返回格式完好但内容为空的上游,在所有只统计状态码的指标里看起来都是成功。


第三层:在健康渠道之间做选择

当一个模型有多个可用渠道时,网关需要一套策略。五种策略几乎覆盖全部真实流量:

  1. 加权轮询 —— 默认选项。摊平负载、让每个健康渠道保持温热,避免过度集中在单一路由。
  2. 最少在途 —— 发给当前活跃请求最少的渠道。当各上游并发上限不一致时最合适。
  3. 成本优先 —— 始终选该模型下最便宜的健康渠道。对批处理和时效不敏感的流量是正确的。
  4. 延迟优先 —— 按近期首 token 时间选择,并加衰减,避免单个快样本主导决策。
  5. 粘性路由 —— 把某个调用方或会话固定到某渠道,谨慎使用,主要用于提示词缓存亲和。

最要紧的工程细节是:策略选择必须便宜且稳定。一个每次请求都重算全局成本模型的路由器,会先被自己的记账拖垮,而不是被上游拖垮。

核心洞察:成本优先路由是网关的价值所在。根据 TokenPAPA 平台公开单价(2026 年 9 月),DeepSeek V4 Flash 输入为每 100 万 token $0.14,而 GPT-5.6 Sol 为 $13.50——因此,让日常流量留在经济档的路由策略,价值远超任何谈下来的折扣。


第四层:两种形态的缓存

网关层的缓存有两种,经济性完全不同。

精确匹配的响应缓存把「模型 + 消息 + 采样参数」的哈希作为键,存完整的请求响应对。这是最便宜的一笔收益,但只在提示词逐字重复时才成立,而且只在确定性配置下才正确。温度不为 0 时,返回缓存补全会静默改变产品行为。

提示词前缀缓存发生在上游,重要得多。DeepSeek 的自动上下文缓存能在前缀逐字节稳定时把重复输入成本砍掉约 90%:同一个系统提示词、同一批检索上下文、同一组工具定义。网关在这里的贡献是不要破坏它——不要重排 system 消息、不要把时间戳注入提示词、不要每次请求都打乱工具顺序。

这是一条挂着营收的设计规则。系统提示词开头的一个非确定性 token,如果每次请求都重建,就能让整个集群的缓存全部失效。


第五层:限流、配额与公平性

限流有三件不同的活,单个限流器做不完:

限流类型作用范围目的
请求速率每 Key、每分钟粗粒度防滥用
token 吞吐每 Key、每分钟,输入加输出真正对应成本的那条限制
并发数每 Key、每渠道保护慢上游不被压垮
预算配额每 Key、每天或每月在跑飞的循环变成账单之前拦住它

token 吞吐是最重要的一条,也最难做,因为输出 token 只有在流推进过程中才逐步可知。可行做法是在请求时按 max_tokens 预留额度,等流结束后再按实际用量核销。缺少预留这一步,大量长输出请求会同时通过前置检查。

按渠道的限额同样重要。某个客户端拿到 429,不应该是因为另一个客户端把同一条上游路由打满了。因此渠道并发必须与 Key 并发分开统计,并在路由的那一刻平衡两个预算。


第六层:可观测性与计费的事实基础

可观测性层有一条不可妥协的要求:任何请求事后都必须可归因。 一条请求记录至少需要包含:API Key、请求的模型、实际承接的渠道、做出该选择的路由决策、上游请求 ID、输入与输出 token 数、缓存命中 token 数、首 token 时间、总耗时、重试链路,以及计算出的成本。

有了这条记录,三个原本无法回答的问题才能回答:

  • 流量没涨,为什么上个月账单高了 30%?
  • 凌晨 3 点那次延迟回归,是哪个上游造成的?
  • 是模型的输出质量变了,还是流量悄悄换到了另一条渠道?

计费是同一份数据的另一端。每家厂商的上报格式都不一样——有的给 prompt 与 completion token,有的把缓存命中与未命中输入分开,有的在流式响应里干脆不返回用量——所以网关把每个响应归一化成一条内部用量记录,再套一套价目表。正是这一步归一化,才让横跨 65 个模型 ID 的单一余额成为可能。

关键结论:如果你无法从自己的日志里重建单次请求的成本,那你拥有的不是计费系统,而是别人给你的一张账单。


端到端的路由路径

把上面几层拼起来,单个请求的路径是这样的:

# 网关请求路径伪代码 —— 上面各层按顺序落地
def handle_request(request):
    key = authenticate(request)                    # 谁在调用
    model = resolve_model_id(request.model)        # 展示名 -> 真实 ID
    check_key_limits(key, request)                 # 速率、并发、预算

    candidates = registry.channels_for(model)      # 第一层
    channel = select(candidates, policy=request.policy)  # 第三层

    reserve_tokens(key, request.max_tokens)        # 第五层
    with channel.slot():                           # 渠道级并发
        try:
            resp = channel.forward(request)
            if resp.is_empty():                    # 静默故障场景
                raise EmptyCompletion()
        except RetryableError:
            channel.mark_degraded()                # 第二层
            channel = select(registry.healthy_for(model), policy=request.policy)
            resp = channel.forward(request)        # 最后一道故障转移

    usage = normalise_usage(resp)                  # 第六层
    reconcile_tokens(key, usage)
    record(key, model, channel, resp, usage)       # 可观测性
    return resp

请注意顺序。最容易放错位置的两步是 reserve_tokens(必须在调用上游之前完成,而不是之后)和 channel.slot()(必须持有整个流式输出期间,而不只是建连阶段)。


这些换来的是什么

以上每一层,都为了支撑一个主张:调用方可以把 60 多个模型当成一个服务来用。

关注点逐一对接各厂商通过统一网关
凭据每家一个 Key,各自轮换一个 Key,一次轮换
SDK 与约定鉴权头、流式格式、工具调用 schema 各不相同一个 OpenAI 兼容客户端
故障转移需要你自己逐家实现和维护在路由环节完成
成本可见性每家一个面板、一张发票一条用量记录、一个余额
接入门槛若干中国厂商要求中国手机号与本地支付邮箱、Google 或 GitHub,国际信用卡以美元结算
切换模型一个新的集成项目改一处 model=

代价也是真实存在的,值得直说:直连让你离厂商最近,新特性当天可用。网关换来的是覆盖面、故障转移和一份统一契约,并在多数模型上收取路由加价。判断时应该看总体拥有成本,而不只是价目表本身。


快速开始

from openai import OpenAI

client = OpenAI(
    api_key="your-tokenpapa-key",
    base_url="https://tokenpapa.ai/v1",
)

def ask(prompt: str, model: str = "deepseek-v4-flash") -> str:
    resp = client.chat.completions.create(
        model=model,                 # 任意在线 ID:gpt-5.6-luna、claude-sonnet-4-6、qwen3.7-plus、kimi-k3
        messages=[{"role": "user", "content": prompt}],
        max_tokens=600,              # 限制输出:输出 token 单价是输入的 3 到 10 倍
    )
    return resp.choices[0].message.content

print(ask("把这个更新日志总结成 5 条要点。"))

两个习惯能让集群从「接通了」变成「可靠」:

  1. 每次调用都限制输出 token。 上表模型的输出单价是输入的 3 到 10 倍,而不设上限的生成同时也是一次不设上限的并发占用。
  2. 保持提示词前缀逐字节稳定。 这是解锁自动上下文缓存那约 90% 重复输入节省的前提。

常见问题

Q: 如何在横跨数十个模型的同时不给路由增加延迟?

A: 路由必须与请求准备并行发生,而不是串行排在前面。网关从内存中的渠道注册表把 model ID 解析为具体渠道、选出一个健康上游,并在请求体还在读取时就开始建连。健康路径上的成本只是一次查表加一次连接选择,而不是多一跳独立的调度服务。额外的跳数只出现在故障转移路径上——某次尝试失败后改用第二个渠道。

Q: 上游厂商在请求中途挂掉会怎样?

A: 网关把首个 token 之前发生的失败与已经开始流式输出之后的失败区别处理。如果还没有任何内容返回给客户端,请求可以在同一模型的第二个健康渠道上重试,调用方看到的是一次更慢的成功而不是报错。如果 token 已经在往外推,则干净地关闭流并上报失败——中途悄悄切换上游会产出前后拼接、语义断裂的回答。

Q: 怎么避免 60 个模型变成 60 张账单?

A: 计费在网关层做归一化。每个上游的用量上报方式都不一样,有的只给 prompt 与 completion token,有的把缓存命中与未命中的输入分开统计,因此每个响应都会被映射成一条内部用量记录:模型、输入 token 数、输出 token 数、缓存命中数。之后只用一套价目表结算,调用方无论请求被哪个上游承接,看到的都是同一个余额和同一张账单。

Q: 统一网关为什么可能比直连厂商更贵?

A: 多数模型上网关确实会带来路由加价,因为它要按上游价结算,同时承担基础设施、故障转移容量与支持成本。也有部分模型定价低于官方原价——例如 Kimi K3 在 TokenPAPA 上约比官方低 10%。诚实的比较应该看总体拥有成本:一次集成、一份凭据、一张账单,对比为每一家厂商单独维护 SDK、鉴权流程、重试策略和发票。权威依据是公示价目表,而不是某篇文章。


立即开始

  1. 注册:前往 tokenpapa.ai/register,支持邮箱、Google 或 GitHub——不需要中国手机号。
  2. 创建 API Key:在控制台生成 Key,用国际信用卡最低 $10 起充,按量计费、以美元结算。
  3. 把任何 OpenAI 兼容客户端指向端点,从经济档起步:
from openai import OpenAI

client = OpenAI(api_key="your-key", base_url="https://tokenpapa.ai/v1")

response = client.chat.completions.create(
    model="deepseek-v4-flash",   # 或 deepseek-v4-pro、gpt-5.6-luna、claude-sonnet-4-6
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=400,              # 始终限制输出 token
)

print(response.choices[0].message.content)

完整价目表:tokenpapa.ai/pricing。实时模型列表:GET https://tokenpapa.ai/v1/models。


本文讲的是路由架构与设计原则,不涉及内部容量或客户数据。文中模型价格为 2026 年 9 月的 TokenPAPA 平台单价,可能发生变动;在制定预算前请以定价页的实时价格为准。

这篇文档对您有帮助吗?

我们如何每天路由 100 万+ 次 API 调用、横跨 60 个模型 | TokenPAPA