AI Agent异步处理:不阻塞主流程的后台任务
Agent 发一封邮件等了 3 秒才回用户。同步等结果是最容易被忽略的体验损耗,这篇讲清什么时候该异步、用队列怎么做、以及状态回传和幂等的实现要点。
💡 你将学到
Agent 发一封邮件等了 3 秒才回用户。同步等结果是最容易被忽略的体验损耗,这篇讲清什么时候该异步、用队列怎么做、以及状态回传和幂等的实现要点。
AI Agent异步处理:用任务队列和状态回传替代同步等待
同步等待是 Agent 体验最大的黑洞
用户发一句"帮我整理这周的会议记录并发到群里",Agent 要先检索、再总结、再调用邮件或群机器人接口。整个过程 5 到 30 秒,如果同步等,用户看到的是转圈;浏览器超时、网关超时、用户重复点击,故障多半从这里开始。
异步的思路很简单:需要用户马上看到的先返回,耗时的丢到后台,完成后再推送。这篇按"判断 → 方案 → 实现要点 → 坑"讲完。
什么时候该异步
| 场景 | 建议 | 原因 |
|---|---|---|
| 单次问答、查天气 | 同步 | 1-3 秒内返回,加队列反而添乱 |
| 多步检索 + 总结 | 异步或流式 | 10 秒以上,同步体验崩 |
| 批量处理 100 份文档 | 异步 | 分钟级,必须后台 |
| 发邮件、写日历、调外部 API | 异步 | 失败要重试,不能让用户等 |
| 长时间代码执行 | 异步 + 沙箱 | 有超时风险 |
| 需要中间结果的任务 | 流式 | 用户要看到进度 |
判断标准可以量化:预期耗时超过 5 秒,或者操作本身可能失败需要重试,就该异步。
三种实现方案
| 方案 | 机制 | 优点 | 代价 |
|---|---|---|---|
| 后台任务 | 进程内起后台任务,返回任务 ID | 零依赖,改几行就能上 | 进程重启丢任务,不适合重活 |
| 消息队列 | Redis + Celery/RQ/arq 等 | 可靠、可重试、可扩容 | 要部署 Redis 和 worker |
| 流式 + 阶段性结果 | SSE 或 WebSocket 推中间状态 | 体验最好,用户看到进度 | 实现复杂,长连接要处理断线 |
实践中的常见组合:交互式请求用流式,批量和副作用操作用消息队列。
实现要点
1. 任务 ID 与状态存储
用户拿到的是一个任务 ID,不是结果。状态机至少要有:排队中 / 执行中 / 已完成 / 失败。状态要放在共享存储(Redis 或数据库),不能只存在 worker 进程内存里。
2. 幂等
队列天然会重复投递(超时重投、worker 被 kill 后重跑)。凡是写操作都要能识别重复:用任务 ID 做去重键,或者让下游接口支持幂等键。
from celery import Celery
app = Celery("agent", broker="redis://localhost:6379/0",
backend="redis://localhost:6379/1")
@app.task(bind=True, max_retries=3, acks_late=True)
def process_request(self, task_id: str, user_input: str):
if already_done(task_id):
return get_result(task_id)
result = agent.run(user_input)
save_result(task_id, result)
notify_user(task_id, result)
return result
3. 超时与重试
给每个任务设硬超时(防止个别任务永久占位),给重试设上限和退避间隔。重试只针对可重试错误(网络超时、429),参数错误、内容违规不要重试。
4. 结果投递
结果出来要主动通知用户:站内轮询、WebSocket 推送、或落到消息队列由前端消费。只写数据库不通知,用户就以为任务丢了。
5. 队列优先级
交互式请求和批量任务混在一条队列里,批量会把队列堵满。分两条队列,或给任务加优先级权重。
前端怎么配合
最小可用的做法是轮询:前端每 1-2 秒查一次任务状态,看到完成就取结果。更顺的做法是 SSE,服务端持续推状态,前端不用反复请求,也便于显示"正在检索""正在生成"这类阶段信息。
注意给轮询设置上限(比如 5 分钟后停止并提示),否则用户关掉页面,你还在为它发请求。
常见坑
- 结果写进数据库但不通知,用户以为失败又点一次,于是执行两遍
- 没有幂等,重试导致重复发邮件或重复扣款
- 任务状态只存在 worker 内存,重启后全部丢失
- 队列没有超时,一个卡住的任务让后面的永远排不上
- 直接把大对象塞进队列消息里,消息体积膨胀影响吞吐
- 忽略流式场景的 token 统计,账目对不上
常见问题
Q:小项目一定要上 Redis 吗? A:不一定。单机、任务少、允许进程重启丢任务时,用框架自带的后台任务足够。会重试、会扩容、会重启的场景再上队列。
Q:异步之后用户看不到结果怎么办? A:把"任务已接受"和"任务完成"两次都显式反馈给用户,并在界面上保留任务历史,让用户能回来查。这是异步设计里最常被偷懒的部分。
Q:任务执行时间未知怎么设超时? A:先按 P95 耗时的 2 到 3 倍设,观察实际超时比例再调整。超时不是失败,可以降级成"只返回已完成部分"。
Q:异步任务卡住怎么排查? A:先看队列积压量,再看 worker 是否存活,最后看单个任务的日志与外部依赖耗时。这三层能把问题范围缩到很小。
相关文章
本站文章由编辑人工撰写,收录的工具均经过实测或公开资料核验。文中链接指向工具官网或 GitHub 仓库,仅作信息参考,不构成付费推广。
