后台任务
规则
- 将耗时任务卸载到后台作业:邮件、图片处理、Webhook、报告、AI 调用
- BullMQ 用于自托管 Redis 队列 — Inngest 或 Trigger.dev 用于无服务器/托管方案
- 每个任务必须幂等 — 重试时不产生副作用(使用幂等键)
- 使用指数退避重试:3-5 次尝试,延迟时间分别为 1 秒、10 秒、60 秒、5 分钟
- 死信队列(DLQ):超过最大重试次数后,将任务移入 DLQ 进行调查 — 绝不静默丢弃
- 设置每个队列的并发限制 — 防止工作器过载(例如
concurrency: 5)
- 任务负载应保持小巧:传递 ID 和引用,而非完整对象
- 按优先级分离队列:
critical(支付)、default(邮件)、low(分析)
- 监控队列深度和处理时间 — 当队列积压时发出警报
模式
import { Queue, Worker } from "bullmq";
const queue = new Queue("emails", { connection: redis });
await queue.add("welcome", { userId }, {
attempts: 3,
backoff: { type: "exponential", delay: 1000 },
});
const worker = new Worker("emails", async (job) => {
await sendWelcomeEmail(job.data.userId);
}, { connection: redis, concurrency: 5 });
import { inngest } from "./client";
export const sendEmail = inngest.createFunction(
{ id: "send-welcome-email", retries: 3 },
{ event: "user/created" },
async ({ event }) => { await sendWelcomeEmail(event.data.userId); }
);
应避免
- 在 API 请求处理程序中处理耗时任务 — 快速响应,后台处理
- 非幂等任务 — 重复执行会导致重复扣费、重复发送邮件
- 无限制的并发 — 将耗尽数据库连接和内存
- 在任务队列中存储大型负载 — 传递引用替代