2012-01-19 4 views
18

Attualmente, il mio ambiente di produzione per un progetto parallelo è un repository git, in cui inserisco del codice, abbandono manualmente il server con Ctrl-C e lo riavvio manualmente.Come riavviare con garbo un server NodeJS?

Mi rendo conto che ci sono molte cose sbagliate in questo. Per esempio, cosa succede se un utente è ancora nel mezzo di fare qualcosa di importante e il processo sta scricchiolando dati sensibili, e l'ho appena ucciso ?!

Quando ho usato il nodo v0.4.x c'era un bel modulo di Cluster che poteva riavviare il server con garbo, quando l'applicazione si trova in uno stato silenzioso. In v0.6.x il modulo Cluster è incorporato nel nodo, ma è veramente, veramente spoglio e non ha la capacità di riavvio aggraziato.

Qualcuno sa come posso riavviare con garbo un server nodejs in v0.6.x?

risposta

2

C'è un modulo denominato Forever.

Questo può riavviare correttamente il processo. Suppongo che tu possa in qualche modo eseguire diverse istanze con cluster (uno su ciascun core) e utilizzare Forever per monitorarle/riavviarle.

Questa è solo un'opzione che ho trovato; Sono aperto ai suggerimenti!

16

È possibile gestire i segnali POSIX nel codice nodo.

Vedere nel codice di esempio, che gestirà SIGINT (Ctrl-C per esempio) come un segnale di STOP per tutti i lavoratori del cluster, e SIGUSR2 sarà solo riavviare tutti i lavoratori

Così, l'emissione di kill -SIGUSR2 PID, dove PID è padrone nodo PID si riavvierà tutti grappolo

module.exports = function(app) { 
    var cluster = require('cluster'); 
    var numCPUs = require('os').cpus().length; 
    var workerList = new Array(); 
    var sigkill = false; 

    if (cluster.isMaster) { 
     for (var i = 0; i < numCPUs; i++) { 
      var env = process.env; 
      var worker = cluster.fork(env); 
      workerList.push(worker); 
     } 

     process.on('SIGUSR2',function(){ 
      console.log("Received SIGUSR2 from system"); 
      console.log("There are " + workerList.length + " workers running"); 
      workerList.forEach(function(worker){ 
       console.log("Sending STOP message to worker PID=" + worker.pid); 
       worker.send({cmd: "stop"}); 
      }); 
     }); 

     process.on('SIGINT',function(){ 
      sigint = true; 
      process.exit(); 
     }); 

     cluster.on('death', function(worker) { 
      if (sigkill) { 
       logger.warn("SIGKINT received - not respawning workers"); 
       return; 
      } 
      var newWorker = cluster.fork(); 
      console.log('Worker ' + worker.pid + ' died and it will be re-spawned'); 

      removeWorkerFromListByPID(worker.pid); 
      workerList.push(newWorker); 
     }); 
    } else { 
     process.on('message', function(msg) { 
      if (msg.cmd && msg.cmd == 'stop') { 
       console.log("Received STOP signal from master"); 
       app.close(); 
       process.exit(); 
      } 
     }); 
     app.listen(3000); 
    } 

    function removeWorkerFromListByPID(pid) { 
     var counter = -1; 
     workerList.forEach(function(worker){ 
      ++counter; 
      if (worker.pid === pid) { 
       workerList.splice(counter, 1); 
      } 
     }); 
    } 
} 
+0

Il gestore 'SIGUSR2' non deve eseguire qualcosa per riavviare il processo appena interrotto? –

+0

Oh, capisco ... Penso che l'evento "morte" sia ora "uscita" nel nodo v0.10? –

+0

Un'altra domanda ... questo riavvia il server con garbo, ma non ricarica affatto il codice del server, giusto? Ciò richiederebbe una sorta di processo di monitoraggio esterno? –

1

C'è anche un modulo denominato PM2. Ha la capacità di arrestare tutti i processi in un cluster.

+0

-1; Ho provato la funzionalità di ricarica "aggraziato" di PM2 e per quanto posso dire [semplicemente non funziona] (https://github.com/Unitech/pm2/issues/3078) adesso. Non posso promettere che nessuna delle altre risposte qui funzioni meglio, ma sono * sicuro * che questo è un vicolo cieco frustrante e che fa perdere tempo. –