Si consideri la seguente applicazione semplice Node.js:Nodo js - http.request() problemi con il pool di connessioni
var http = require('http');
http.createServer(function() { }).listen(8124); // Prevent process shutting down
var requestNo = 1;
var maxRequests = 2000;
function requestTest() {
http.request({ host: 'www.google.com', method: 'GET' }, function(res) {
console.log('Completed ' + (requestNo++));
if (requestNo <= maxRequests) {
requestTest();
}
}).end();
}
requestTest();
Rende 2000 le richieste HTTP a google.com, uno dopo l'altro. Il problema è che si ottiene la richiesta n. 5 e si interrompe per circa 3 minuti, quindi continua l'elaborazione delle richieste da 6 a 10, quindi si interrompe per altri 3 minuti, quindi si richiedono 11-15, pause e così via. Modifica:Ho provato a cambiare www.google.com in localhost, un'app Node.js estremamente semplice che esegue la mia macchina che restituisce "Hello world", ho ancora la pausa di 3 minuti.
Ora ho letto posso aumentare il limite di pool di connessioni:
http.globalAgent.maxSockets = 20;
Ora, se l'eseguo, esso elabora le richieste 1-20, poi si ferma per 3 minuti, quindi richiede 21 - 40, quindi le pause , e così via.
Infine, dopo un po 'di ricerca, ho imparato ho potuto disattivare il pool di connessioni interamente impostando agent: false
nelle opzioni di richiesta:
http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
...snip....
... e sarà gestita attraverso tutti 2000 le richieste più che bene.
La mia domanda, è una buona idea farlo? C'è il pericolo che io possa finire con troppe connessioni HTTP? E perché si ferma per 3 minuti, sicuramente se ho finito con la connessione dovrebbe aggiungerlo direttamente in piscina pronto per la prossima richiesta da usare, quindi perché aspetta 3 minuti? Perdona la mia ignoranza.
In caso contrario, qual è la strategia migliore per un'app Node.js che effettua un numero potenzialmente elevato di richieste HTTP, senza blocco o arresto anomalo?
Sto eseguendo Node.js versione 0.10 su Mac OS X 10.8.2.
Edit: ho trovato se converto il codice sopra in un ciclo for e cercare di stabilire una serie di connessioni, allo stesso tempo, ho iniziare a ricevere gli errori dopo circa 242 connessioni. L'errore è:
Error was thrown: connect EMFILE
(libuv) Failed to create kqueue (24)
... e il codice ...
for (var i = 1; i <= 2000; i++) {
(function(requestNo) {
var request = http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
console.log('Completed ' + requestNo);
});
request.on('error', function(e) {
console.log(e.name + ' was thrown: ' + e.message);
});
request.end();
})(i);
}
non so se un Node.js app pesantemente caricato potrebbe mai raggiungere quel numero di connessioni simultanee.
Si stanno esaurendo i descrittori di file, che su OSX sono limitati a un 256 piuttosto basso per impostazione predefinita. Puoi aumentare quel numero usando 'ulimit -n 2048', che consentirebbe un successivo processo di nodo eseguito dalla stessa shell per aprire quelle 2000 connessioni a Google ** allo stesso tempo **, ma non è proprio quello che vuoi . Non sono sicuro di dove arrivino i 3 minuti, suona come una strozzatura nel pool di connessione (o forse Google ti sta soffocando?). – robertklep
Grazie per le informazioni sui descrittori di file OSX, ha un po 'più senso. Immagino che non sarebbe un problema su un sito live in esecuzione su Linux. Ma per quanto riguarda i 3 minuti di attesa, ho capito che se avessi colpito un'applicazione web Node.js in esecuzione sul mio computer. –
Leggendo [questo] (http://nodejs.org/api/http.html#http_class_http_agent), mi chiedo se il timeout di 3 minuti sia il timeout keep-alive per i server di Google (anche se comprendo correttamente i documenti, come a mano a mano che continui a richiedere, non dovrebbe aspettare la scadenza dei keep-alive prima di iniziare una nuova richiesta ...) – robertklep