示例说明
发邮件、生成报表这类耗时操作不应阻塞 HTTP 响应。BullMQ 基于 Redis 实现持久化队列:任务落盘后在独立 Worker 进程消费,失败自动按指数退避重试,进程崩溃后未完成任务仍在 Redis 中可恢复。removeOnComplete 控制已完成任务的保留数量,避免 Redis 无限膨胀。
技术要点
- attempts 与 exponential backoff 控制重试策略
- concurrency 设定单 Worker 的并行消费数
- failed 事件暴露最终失败供告警
代码解读
生产者用 mailQueue.add 提交任务并附带重试选项,delay 是首次退避基数;Worker 构造时传入同名队列与连接配置,处理函数里抛错即触发重试,attemptsMade 可用来区分首次执行。failed 事件表示重试耗尽后的终态,应接入告警而不是静默丢弃。
使用建议
任务函数要保持幂等,重试可能造成重复副作用。连接配置建议复用 IORedis 实例并开启 maxRetriesPerRequest 的合理值。removeOnFail 保留量要够事后排查,但也要设置上限。
代码示例
import { Queue, Worker } from 'bullmq';
const connection = { url: 'redis://127.0.0.1:6379' };
const mailQueue = new Queue('mail', { connection });
await mailQueue.add('send-welcome', { userId: 42 }, {
attempts: 5,
backoff: { type: 'exponential', delay: 2000 },
removeOnComplete: 100,
removeOnFail: 1000,
});
const worker = new Worker('mail', async (job) => {
if (job.attemptsMade < 1) throw new Error('smtp temporarily unavailable');
console.log('delivered mail for', job.data.userId);
}, { connection, concurrency: 4 });
worker.on('failed', (job, err) => {
console.error('job failed', job.id, err.message);
});