Agenda 任务调度入门:MongoDB 驱动的 Node.js 定时任务
Agenda 用 MongoDB 持久化任务队列:cron 语法与人类可读格式双支持、任务管理 API、Agendash 监控面板。本文讲解调度、配置与生产监控。
Agenda 是持久化任务调度器:任务定义存 MongoDB,进程重启不丢,agenda.every('5 minutes', 'job-name') 调度周期任务、agenda.schedule('in 20 minutes') 安排一次性任务。相比 Node-cron 的内存调度,它解决了重启丢失与多实例协调问题。
为什么是 Agenda
Node-cron 的任务活在内存里:进程重启全丢、多实例各跑各的。Agenda 把任务存进 MongoDB——任务即数据:重启恢复、多实例互斥消费、执行历史可查。
基础调度
npm install agenda
const { Agenda } = require('agenda');
const agenda = new Agenda({ db: { address: 'mongodb://localhost:27017/agenda' } });
// 定义任务
agenda.define('send-welcome-email', async (job) => {
const { userId } = job.attrs.data;
await sendEmail(userId);
});
await agenda.start();
// 每 5 分钟周期执行
await agenda.every('5 minutes', 'cleanup-expired-sessions');
// 20 分钟后执行一次
await agenda.schedule('in 20 minutes', 'send-welcome-email', { userId: 123 });
// cron 表达式也行
await agenda.every('0 2 * * *', 'daily-backup');
任务配置选项
agenda.define('heavy-report', {
concurrency: 2, // 该任务最多并发 2 个
lockLifetime: 10 * 60 * 1000, // 锁 10 分钟(防实例崩溃后任务卡死)
priority: 'high',
}, async (job) => { /* ... */ });
- concurrency:控制同任务并行度,保护下游资源;
- lockLifetime:实例崩溃后锁超时释放,任务被其他实例接管——多实例可靠性的关键;
- priority:紧急任务插队。
调度频率的选择
every() 适合固定节奏;任务执行耗时波动大时注意:执行时间超过间隔会堆积。用 lockLimit 限制堆积,或改用"上次完成后再排下一次"的自调度模式。
Agendash 监控面板
npm install agendash
Agendash 提供 Web 面板:任务列表、执行历史、失败重试、手动触发——接进 Express 一个路由即可(生产务必加认证)。
发现 Agenda 任务的静默积压
Agenda 的锁和轮询可能让任务迟迟不开始。记录任务计划时间、真正开始时间、完成状态与锁超时信息,把等待延迟和失败次数送入观测云,再按任务名称设置检测条件。数据库连接正常只证明 MongoDB 可用;监控任务是否按期完成,还需要应用主动写入完成事件,并验证停机、锁超时和重试耗尽的告警路径。
接入文档:日志采集 · Prometheus 指标采集 · 监控器与告警策略。
常见问题(FAQ)
Q:Agenda 和 BullMQ 怎么选?
用 Redis 的选 BullMQ(性能更强、生态更活跃);已用 MongoDB 想复用基础设施选 Agenda。纯定时调度两者都行。
Q:多实例部署任务会重复执行吗?
不会——MongoDB 锁机制保证一个任务实例只被一个进程消费。这正是 Agenda 相比 Node-cron 的核心价值。
Q:任务数据(data)该放多少?
放 ID 不放快照:{ userId: 123 } 而非整个 user 对象——执行时查最新数据,避免"任务排队时的旧数据"问题。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。