Saltar al contenido

¿Cómo ejecutar Cron Job en la aplicación Node.js que usa el módulo de clúster?

Ya no tienes que buscar más por todo internet porque estás al espacio exacto, contamos con la respuesta que buscas pero sin complicaciones.

Solución:

si están usando PM2puede utilizar una variable de entorno proporcionada por PM2 se llama a sí mismo NODE_APP_INSTANCE que requiere PM2 2.5 o mayor.

NODE_APP_INSTANCE la variable de entorno se puede usar para determinar la diferencia entre procesos, por ejemplo, es posible que desee ejecutar un cronjob solo en un proceso, puede hacer esto

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

,

Dado que dos procesos nunca pueden tener el mismo número.

Más información sobre el documento oficial de PM2 aquí.

Después de investigar un poco, terminé con la solución “Bloqueos distribuidos usando Redis”. Hay un módulo de nodo para eso: node-redis-warlock.

Espero que esta respuesta sea útil para alguien más.

ACTUALIZAR. Código de muestra mínimo:

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();          
);

ACTUALIZAR 2. Ejemplo más detallado:

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...

De hecho, no me gusta el enfoque de redis que también se usa en el complemento cron-cluster npm, porque no quiero tener ese servidor redis ejecutándose en mi máquina y mantenerlo también.

Me gustaría discutir este enfoque con usted:

Pro: no necesitamos usar redis Contra: los trabajos cron siempre se ejecutan en el mismo trabajador

Uso el paso de mensajes solo para esto, si lo usas para otras cosas, quieres pasar la información que

if (cluster.isMaster) 
    // Count the machine's CPUs
    var cpuCount = require('os').cpus().length;;

    // Create a worker for each CPU
    for (var i = 0; i < cpuCount; i += 1) 
        cluster.fork();
    

    cluster.on('fork', (worker) => 
        console.log("cluster forking new worker", worker.id);
    );

    // have a mainWorker that does the cron jobs.
    var mainWorkerId = null;

    cluster.on('listening', (worker, address) => 
        console.log("cluster listening new worker", worker.id);
        if(null === mainWorkerId) 
            console.log("Making worker " + worker.id + " to main worker");
            mainWorkerId = worker.id;
        worker.send(order: "startCron");
        
    );

    // Listen for dying workers if the mainWorker dies, make a new mainWorker
    cluster.on('exit', function (worker, code, signal) 
        console.log('Worker %d died :(', worker.id);

        if(worker.id === mainWorkerId) 
            console.log("Main Worker is dead...");
            mainWorkerId = null;
        

        console.trace("I am here");
        console.log(worker);
        console.log(code);
        console.log(signal);
        cluster.fork();

    );
// Code to run if we're in a worker process
 else 

    // other code like setup app and stuff

    var doCron = function() 
        // setup cron jobs...
    

    // Receive messages from the master process.
    process.on('message', function(msg) 
        console.log('Worker ' + process.pid + ' received message from master.', message);
        if(message.order == "startCron") 
            doCron();
        
    );

Sección de Reseñas y Valoraciones

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *