综合 / 人工智能 · 2026-10-01 15:08 · 6 阅读 · 0 赞
生产环境 LLM 任务流水线:Token 预算、背压与异步队列架构
将 LLM 集成进企业级 SaaS 时,同步 HTTP 调用会带来线程池耗尽、供应商限流级联和费用失控。本文介绍基于异步消息队列、Token 权重估算与动态限流的流水线设计,实现 Token 预算管控、背压与优雅降级。
把 LLM 能力集成进企业级 SaaS,不能只靠简单的同步 HTTP 调用。当请求量激增时,供应商的速率限制(每分钟 Token 数 TPM 与每分钟请求数 RPM)以及不可预测的推理延迟,都可能拖垮你的后端。
下面介绍如何设计带 Token 预算节流、Worker 背压和优雅降级的异步 LLM 队列流水线。
1. 同步调用 LLM 的问题
在 HTTP 请求处理函数里直接执行模型调用(例如 GPT-4o、Claude 3.5 Sonnet,或自托管的 vLLM 实例),会给 Web 应用服务器带来系统性风险:
- 线程池耗尽: 长时间运行的推理查询(5 到 30 秒)会占住 Web 服务器的连接工作线程,在并发流量下迅速耗尽套接字池。
- 供应商限流级联: 未加节流的突发请求会突破供应商的 RPM 或 TPM 上限,触发 HTTP 429 错误,并在客户端应用中引发级联故障。
- 不可预测的费用尖峰: 缺少集中式的队列并发管理,就很难在多租户场景下执行全局计费护栏和 Token 预算安全网。
2. 架构蓝图:Token 感知的队列流水线
生产级流水线通过异步消息中间件(例如 Redis 配合 BullMQ)把任务提交与模型执行解耦,并叠加一层动态限流,在调用供应商 API 之前先估算 Token 权重。
Token 权重与动态节流
与按离散 HTTP 请求计数的普通 API 限流器不同,LLM 限流器必须跟踪动态的 Token 消耗。在派发任务之前,Worker 会先估算 prompt 的 Token 数,再检查滑动窗口的 Token 桶。
import { Worker, Job } from 'bullmq';
import { Redis } from 'ioredis';
import { getEncoding } from 'js-tiktoken';
const redis = new Redis(process.env.REDIS_URL);
const tokenizer = getEncoding('cl100k_base');
interface LLMJobPayload {
tenantId: string;
prompt: string;
maxTokens: number;
}
export const llmWorker = new Worker<LLMJobPayload>(
'llm-generation-queue',
async (job: Job<LLMJobPayload>) => {
const { tenantId, prompt, maxTokens } = job.data;
// 1. 计算估算的 prompt Token 权重
const promptTokens = tokenizer.encode(prompt).length;
const estimatedTotalTokens = promptTokens + maxTokens;
// 2. 评估当前全局 Token 预算(Redis 中的滑动窗口)
const allowed = await checkTokenBudget(redis, estimatedTotalTokens);
if (!allowed) {
// 动态延迟任务执行,而不是让任务失败
await job.moveToDelayed(Date.now() + 5000, job.token);
throw new Error('RATE_LIMIT_DELAY: Dynamic backpressure applied');
}
// 3. 带超时保护地执行模型 API 调用
const response = await executeModelCall({
prompt,
maxTokens,
timeoutMs: 45000
});
// 4. 根据 API 元数据核对实际消耗的 Token
await reconcileActualTokenUsage(redis, response.usage.total_tokens);
return response.content;
},
{
concurrency: 10,
limiter: {
max: 500,
duration: 60000
}
}
);