2013-06-30 12 views
9

Ho un server nodejs che esegue express per eseguire chiamate http. C'è un approccio consigliato per spegnere il server con grazia se succede qualcosa di brutto? Dovrei lasciare il server in esecuzione in qualche modo?Nodejs/express, shutdown con garbo

I.E. su un'eccezione non rilevata il server si ferma, penso che questo ucciderà sui client connessi e non restituirà loro una risposta.

Dovrei:

  1. Attendere che tutte le connessioni HTTP a completare prima di consentire al server di morire (e poi riavviarlo).
  2. O dovrei provare a fermare la morte del server?

è corretto?

process.on('exit', function() { 
    console.log('About to exit, waiting for remaining connections to complete'); 
    app.close(); 
}); 

In questo caso un errore potrebbe essere stato gettato lasciando il server in uno stato indefinito e il server continuerà a finire le connessioni rimanenti.

C'è qualche buon modo per gestire gli errori continuare a funzionare o devo lasciare morire e riavviare il server?

risposta

6

Non cercare di fare niente di speciale con le eccezioni non gestite. Lascia morire il server.

In genere, se un gestore di route genera un'eccezione, Express lo cattura e restituisce un HTTP 500 al client. Poiché Express ha riscontrato un'eccezione, il tuo server non si arresterà in modo anomalo.

Quello che di solito accade che fa cadere un server è quando un'eccezione viene lanciata all'interno di un callback; per esempio:

app.get('/foo', function(req, res) { 
    db.query(..., function(err, r) { 
     throw new Error(); // oops, we'll crash 
    }); 
}); 

Perché il callback esegue naturalmente al di fuori dello stack di chiamate router Express, non c'è modo per associarlo con una richiesta specifica. Tuttavia, è possibile evitare una situazione del genere:

app.get('/foo', function(req, res, next) { 
    db.query(..., function(err, r) { 
     try { 
      throw new Error(); 
     } catch(ex) { 
      next(ex); 
     } 
    }); 
}); 

Funzione Express next prende un errore come primo argomento. Se si chiama next con un argomento di errore, si fermerà l'elaborazione di percorsi e cercare un error handler, o semplicemente restituire un 500.

Naturalmente, avvolgendo tutto in try/catch è probabilmente eccessivo; la maggior parte delle cose in realtà non genera eccezioni. Lo si dovrebbe fare solo se si conosce qualcosa. Altrimenti, si potrebbe finire in uno stato incoerente molto difficile da debug ingerendo le eccezioni.

È importante ricordare che una volta generata un'eccezione imprevista, l'applicazione si trova in uno stato indefinito. È possibile che la richiesta del problema non venga mai completata e l'app non si riavvierà mai. O potrebbe accadere qualsiasi numero di altre strane cose. (Era un problema di database? Filesystem? Memoria corrotta?)

Questi tipi di situazioni sono incredibilmente difficili da diagnosticare e molto meno debug. È più sicuro e probabilmente meglio fallire rapidamente, crash e riavviare rapidamente il server. Sì, tutti i client che si connettono verrebbero tagliati, ma è abbastanza facile per loro semplicemente riprovare.

Se si è preoccupati della disponibilità, utilizzare cluster module in modo che siano in esecuzione diversi processi del server (in genere numero di core CPU) e un arresto anomalo non comporterà l'arresto dell'intero sito.

+1

Questa è una grande spiegazione. Una cosa non mi è ancora chiara. "È importante ricordare che una volta generata un'eccezione imprevista, la tua applicazione si trova in uno stato indefinito. È possibile che la richiesta del problema non venga mai completata e la tua app non si riavvierà mai più ". Questo suona come se non dovessi chiamare app.vicino(); in corso "uscita". Vero? – lostintranslation

+0

Chiamare 'app.close()' nel 'process'' exit' handler è inutile: il [docs say] (http://nodejs.org/api/process.html#process_event_exit) * "Il ciclo dell'evento principale sarà non viene più eseguito dopo la richiamata di "uscita". * In altre parole, l'evento "exit" ti dice che il processo ** finirà dopo il ritorno della tua funzione. La chiusura di un listener di rete è inutile poiché non esiste un tick successivo; il codice per accettare una connessione in ingresso non avrà mai l'opportunità di essere eseguito. – josh3736

+0

fantastico, grazie! – lostintranslation

5

NodeJS si spegnerà quando non si aspetta che accada qualcosa; Mentre il server http è in attesa di connessioni, il nodo rimane in esecuzione.

server.close([callback])

Arresta il server di accettare nuove connessioni e mantiene connessioni esistenti. Questa funzione è asincrona, il server alla fine è chiuso quando tutte le connessioni sono terminate e il server emette un evento . Facoltativamente, puoi passare una richiamata per ascoltare l'evento close .

Dopo aver eseguito questa operazione, il server continuerà a funzionare fino al termine dell'ultima connessione e quindi a spegnersi correttamente.

Se non si desidera attendere la chiusura delle connessioni, è possibile utilizzare socket.end() o socket.destroy() sulle connessioni rimanenti.

Vedi http://nodejs.org/api/net.html


process.on('exit', function() { 
    console.log('About to exit, waiting for remaining connections to complete'); 
    app.close(); 
}); 

Questa funzione deve eseguire quando esiste il nodo e non effettivamente dire nodo per uscire. Qui è un modo è possibile terminare il processo, ma non finirebbe con garbo:

process.exit([code])

termina il processo con il codice specificato. Se omesso, exit utilizza il codice "successo"0.

Per uscire con un codice 'errore':

process.exit(1); Il guscio che ha eseguito nodo dovrebbe vedere il codice di uscita come 1.

Vedi http://nodejs.org/api/process.html


Spero che questo aiuta!