NestJs项目PM2集群部署下CronJob重复执行如何找单点执行入口
PM2集群模式下NestJS定时任务仅执行一次的解决方案
以下三种方案覆盖不同部署场景,可根据你的实际需求选择:
方案1:利用PM2内置进程变量区分执行节点
PM2集群模式启动时会自动为每个进程注入唯一的NODE_APP_INSTANCE环境变量,值从0开始依次递增,你只需要在定时任务逻辑前增加判断,仅允许编号为0的进程执行任务即可。
NestJS代码示例:
import { Cron } from '@nestjs/schedule'; import { Injectable } from '@nestjs/common'; @Injectable() export class DailyDataUpdateTask { @Cron('0 0 * * *') // 按你的实际定时规则配置 runUpdateTask() { // 非首个实例直接跳过执行 if (process.env.NODE_APP_INSTANCE !== '0') return; // 下方写入你的定时任务业务逻辑 } }
注意:如果你自定义过PM2的
instance_var配置,需要将判断条件中的变量名替换为你自定义的变量名。
方案2:拆分定时任务为独立单实例进程
将定时任务逻辑从业务服务中解耦,PM2启动时单独配置1个单实例进程运行定时任务,业务服务仍保持多集群模式运行,两者完全隔离不会互相干扰。
PM2 ecosystem.config.js配置示例:
module.exports = { apps: [ { name: 'nest-business-api', script: 'dist/main.js', instances: 8, exec_mode: 'cluster', env: { ENABLE_CRON: 'false' } }, { name: 'nest-cron-service', script: 'dist/main.js', instances: 1, exec_mode: 'fork', env: { ENABLE_CRON: 'true' } } ] }
对应的NestJS定时任务判断逻辑:
if (process.env.ENABLE_CRON !== 'true') return;
方案3:分布式锁适配跨机器部署场景
如果你的服务是多机器集群部署,上述单机方案不适用的话,可以基于Redis、数据库等公共存储实现分布式锁:
- 定时任务触发时,所有进程先尝试抢全局唯一的锁
- 只有抢锁成功的进程可以执行任务逻辑
- 任务执行完成后主动释放锁,锁需要设置合理的过期时间避免死锁
你可以直接使用
redlock等成熟的第三方工具库简化分布式锁实现逻辑。
内容的提问来源于stack exchange,提问作者s0ltan.js
相关产品推荐
相关产品推荐

