2026 年 3 月,我们团队把一个 AI 审批系统从 POC 推到生产。第一天就挂了:凌晨 3 点,某个工具调用陷入重试循环,一晚上烧了 $47 的 API 费用,队列积压了 2 万条任务。复盘发现,问题出在三个地方——没有限流、没有超时熔断、没有预算控制。
这篇文章记录了我们从"能跑"到"能扛"的架构演进过程,包含具体的配置和踩坑记录。
一、POC 阶段的典型架构
大多数团队的 POC 长这样:一个 Python 脚本,调 LLM API,循环处理输入。没有持久化、没有重试策略、没有监控。核心逻辑大约 20 行,测试集 50 条数据,挂了 rerun 就行。
但上生产后,三个致命缺陷暴露了:
- 没有超时:LLM 响应慢时,调用会 hang 住直到 TCP 超时(通常 60-120s)
- 没有重试:网络抖动导致 5xx 时直接抛异常
- 没有限流:API rate limit 触发 429 后,全部失败
二、生产 V1:加基础防护
第一轮改造加了三个东西:超时控制、指数退避重试、并发限流。核心改动:
- 用 AsyncOpenAI 替代 OpenAI,设置 timeout=30.0
- 用 tenacity 库做指数退避重试,最多 3 次,等待时间 2-30s
- 用 asyncio.Semaphore(10) 控制最大并发数
这版上线后,p99 延迟从 27s 降到了 8s,429 错误基本消失。但新问题来了:成本不可控。某个指令设计不当导致 LLM 输出 8000 字符,单次调用花了 $0.15。每天 10 万次就是 $15,000。
三、生产 V2:加预算控制与监控
第二轮改造核心是"每一分钱都要看到去向"。
| 维度 | POC 阶段 | 生产 V1 | 生产 V2 |
|---|---|---|---|
| 超时控制 | 无 | 30s 客户端超时 | 分模型超时(gpt-4o: 30s, 快模型: 15s) |
| 重试策略 | 手动 rerun | 指数退避 3 次 | 按错误类型差异化重试 |
| 并发控制 | 无 | Semaphore(10) | 动态限流(根据 API quota 实时调整) |
| 预算控制 | 无 | 无 | 每次调用前预算检查 + 事后审计 |
| 可观测性 | print() | 结构化日志 | Prometheus + 自定义 metrics |
| 持久化 | 无 | SQLite | PostgreSQL + 事件溯源 |
预算控制的实现思路:维护一个滑动窗口(最近 1 分钟)和一个日累计计数器。每次调用前估算消耗量,检查是否超过分钟/日限额。超限则直接拒绝并告警。同时用 Prometheus 暴露三个关键指标:
llm_request_duration_seconds(histogram,按模型和状态分桶)llm_token_consumed_total(counter,按模型分)llm_budget_rejected_total(counter,预算拒绝次数)
四、生产 V3:事件溯源与审计
金融场景要求每一步都有审计日志。我们选择了事件溯源模式:每个任务的完整生命周期被记录为一系列不可变事件。事件类型包括:
- Received:用户提交任务
- Invoked:调用 LLM(记录输入量)
- Responded:LLM 返回(记录输出量和延迟)
- Approved:人工审批通过
存储用 PostgreSQL 的一张 events 表,payload 字段用 JSONB。建表语句:
CREATE TABLE events (
id BIGSERIAL PRIMARY KEY,
trace_id UUID NOT NULL,
event_type VARCHAR(50) NOT NULL,
payload JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_trace ON events(trace_id);
这套设计让排查问题变得简单:给定 trace_id,直接 SQL 查询就能还原完整链路。比如找出所有"LLM 响应时间 > 10s"的条目,关联到对应的输入内容,定位指令设计问题。
五、关键经验总结
- 先加防护再上量:超时、重试、限流这三样在 POC 阶段就写好,成本几乎为零,生产出事再补就晚了。
- 预算控制比 API 单价更值得关注:我们踩的坑里,80% 的成本失控来自指令设计不当导致输出过长,而非模型单价。
- 可观测性要提前埋点:Prometheus + 结构化日志的组合,在排查"凌晨 3 点谁烧了 $47"这种问题时,能把定位时间从 4 小时缩短到 10 分钟。
- 事件溯源是金融场景的底线:没有审计日志,合规审查过不了。PostgreSQL 存 JSONB 事件流,简单可靠,不需要额外引入 Event Store。
六、常见问题(FAQ)
问:Semaphore 限流够用吗?生产环境用什么?
单机场景 Semaphore 够用。分布式场景建议用 Redis 的滑动窗口计数器 + 本地 bucket 两级限流。我们最终用的是 aiolimiter 库 + Redis 做全局协调。
问:事件溯源会不会太重?
看场景。如果只是日志审计,用结构化日志 + 日志中心(ELK/Loki)就够了。事件溯源的优势在于能还原状态——比如"用户看到的结果是什么",而日志只告诉你"调用了什么 API"。
问:每天 10 万次调用,LLM 成本大概多少?
以 gpt-4o 为例,平均每次 500 input + 200 output,单价约 $0.0025/次。10 万次 ≈ $250/天。如果换成 DeepSeek-V4 或本地部署的模型,成本可以降到 $30-50/天。
问:异步架构和同步架构怎么选?
我们的场景是异步的——用户提交后,系统回调通知结果。如果要求实时响应(比如聊天),同步架构更简单,但要做好 30s+ 的等待处理。建议用 WebSocket + 流式输出,避免 HTTP 长连接超时。
问:2026 年有没有推荐的部署工具?
LangGraph 的 LangGraph Server 可以直接部署为微服务,内置 Checkpointer 和 trace。如果团队熟悉 Kubernetes,用 Temporal 做编排层 + 任意框架做执行单元,是目前最灵活的组合。
