如何在使用集群模块的Node.js应用程序中运行Cron Job?

我正在使用Node-cron模块来调度Node.js应用程序中的任务。 我也希望在使用核心集群模块的几个进程中运行应用程序。

在几个进程中运行应用程序最终将在每个进程中执行计划任务(例如,如果任务是发送电子邮件,则会多次发送电子邮件)。

与群集模块一起运行cron作业的最佳实践/可行方法是什么? 我应该创build一个单独的进程,只处理cron作业,不接受任何请求。 如果是的话,我怎样才能以正确的方式做到这一点?

       

网上收集的解决方案 "如何在使用集群模块的Node.js应用程序中运行Cron Job?"

经过一番研究,我最终select了“ 使用Redis的分布式锁 ”解决scheme。 有节点模块: node-redis-warlock 。

希望这个答案对别人有用。

更新 。 最小示例代码:

var Warlock = require('node-redis-warlock'), redis = require('redis'); // Establish a redis client redis = redis.createClient(); // and pass it to warlock var warlock = new Warlock(redis); function executeOnce (key, callback) { warlock.lock(key, 20000, function(err, unlock){ if (err) { // Something went wrong and we weren't able to set a lock return; } if (typeof unlock === 'function') { setTimeout(function() { callback(unlock); }, 1000); } }); } // Executes call back only once executeOnce('every-three-hours-lock', function(unlock) { // Do here any stuff that should be done only once... unlock(); }); 

更新2 。 更详细的例子:

 const CronJob = require('cron').CronJob; const Warlock = require('node-redis-warlock'); const redis = require('redis').createClient(); const warlock = new Warlock(redis); const async = require('async'); function executeOnce (key, callback) { warlock.lock(key, 20000, function(err, unlock) { if (err) { // Something went wrong and we weren't able to set a lock return; } if (typeof unlock === 'function') { setTimeout(function() { callback(unlock); }, 1000); } }); } function everyMinuteJobTasks (unlock) { async.parallel([ sendEmailNotifications, updateSomething, // etc... ], (err) => { if (err) { logger.error(err); } unlock(); }); } let everyMinuteJob = new CronJob({ cronTime: '*/1 * * * *', onTick: function () { executeOnce('every-minute-lock', everyMinuteJobTasks); }, start: true, runOnInit: true }); /* Actual tasks */ let sendEmailNotifications = function(done) { // Do stuff here // Call done() when finished or call done(err) if error occurred } let updateSomething = function(done) { // Do stuff here // Call done() when finished or call done(err) if error occurred } // etc... 

如果正在使用PM2 ,则可以使用由PM2本身提供的环境variables,称为NODE_APP_INSTANCE ,它要求PM2 2.5或更高。

NODE_APP_INSTANCE环境variables可用于确定进程之间的差异,例如,您可能只想在一个进程上运行一个cronjob,您可以这样做

if(process.env.NODE_APP_INSTANCE == 0) { //schedule your cron job here since this part will be executed for only one cluster }

由于两个进程永远不会有相同的编号。

更多信息PM2官方文档在这里 。