Su problema no tiene nada que ver con el bloqueo de llamadas; esto tiene que ver con el hecho de que solo puede abrir una determinada cantidad de conexiones a la vez a un solo host. Una vez que alcanza la cantidad máxima de conexiones abiertas, las otras llamadas asíncronas al http.get
tienen que esperar hasta que el número de conexiones abiertas vuelva a caer, lo que sucede cuando las demás solicitudes se completan y se activan sus devoluciones de llamada. Ya que estás creando nuevas solicitudes más rápido de lo que agotan, obtienes los resultados aparentemente bloqueantes.
Aquí hay una versión modificada de su programa que creé para probar esto. (Tenga en cuenta que hay una manera más fácil de resolver su problema, como lo indica mtomis - más sobre esto a continuación.) Agregué un poco de registro console.log
, por lo que es más fácil saber en qué orden se procesaron las cosas; También rechazo todas las solicitudes para cualquier cosa que no sea /
, por lo que se ignoran las solicitudes favicon.ico
. Finalmente, realizo solicitudes a muchos sitios web.
var http = require('http');
// http://mostpopularwebsites.net/1-50/
var sites = [
"www.google.com", "www.facebook.com", "www.youtube.com",
"www.yahoo.com", "www.blogspot.com", "www.baidu.com", "www.live.com",
"www.wikipedia.org", "www.twitter.com", "www.qq.com", "www.msn.com",
"www.yahoo.co.jp", "www.sina.com.cn", "www.google.co.in", "www.taobao.com",
"www.amazon.com", "www.linkedin.com", "www.google.com.hk",
"www.wordpress.com", "www.google.de", "www.bing.com", "www.google.co.uk",
"www.yandex.ru", "www.ebay.com", "www.google.co.jp", "www.microsoft.com",
"www.google.fr", "www.163.com", "www.google.com.br",
"www.googleusercontent.com", "www.flickr.com"
];
var server = http.createServer(function(req, res) {
console.log("Got a connection.");
if(req.url != "/") {
console.log("But returning because the path was not '/'");
res.end();
return;
}
var counter = 0;
for(var i = 1; i <= 30; i++) {
http.get({ host: sites[i] }, function(index, host, r) {
counter++;
console.log("Response " + counter + " from # " + index + " (" + host + ")");
res.write("Response " + counter + " from # " + index + " (" + host + ")\n");
if(counter == 30) res.end();
}.bind(this, i, sites[i]));
}
console.log("Done with for loop.");
});
server.listen(8000);
que corrió este programa y muy rápidamente visitado la página en dos navegadores diferentes (también Enrojecí mi caché DNS, como la prueba estaba corriendo demasiado rápido para obtener un buen resultado de lo contrario). Aquí está la salida:
Got a connection.
Done with for loop.
Response 1 from # 8 (www.twitter.com)
Response 2 from # 1 (www.facebook.com)
Response 3 from # 12 (www.sina.com.cn)
Response 4 from # 4 (www.blogspot.com)
Response 5 from # 13 (www.google.co.in)
Response 6 from # 19 (www.google.de)
Response 7 from # 26 (www.google.fr)
Response 8 from # 28 (www.google.com.br)
Response 9 from # 17 (www.google.com.hk)
Response 10 from # 6 (www.live.com)
Response 11 from # 20 (www.bing.com)
Response 12 from # 29 (www.googleusercontent.com)
Got a connection.
Done with for loop.
Response 13 from # 10 (www.msn.com)
Response 14 from # 2 (www.youtube.com)
Response 15 from # 18 (www.wordpress.com)
Response 16 from # 16 (www.linkedin.com)
Response 17 from # 7 (www.wikipedia.org)
Response 18 from # 3 (www.yahoo.com)
Response 19 from # 15 (www.amazon.com)
Response 1 from # 6 (www.live.com)
Response 2 from # 1 (www.facebook.com)
Response 3 from # 8 (www.twitter.com)
Response 4 from # 4 (www.blogspot.com)
Response 20 from # 11 (www.yahoo.co.jp)
Response 21 from # 9 (www.qq.com)
Response 5 from # 2 (www.youtube.com)
Response 6 from # 13 (www.google.co.in)
Response 7 from # 10 (www.msn.com)
Response 8 from # 24 (www.google.co.jp)
Response 9 from # 17 (www.google.com.hk)
Response 10 from # 18 (www.wordpress.com)
Response 11 from # 16 (www.linkedin.com)
Response 12 from # 3 (www.yahoo.com)
Response 13 from # 12 (www.sina.com.cn)
Response 14 from # 11 (www.yahoo.co.jp)
Response 15 from # 7 (www.wikipedia.org)
Response 16 from # 15 (www.amazon.com)
Response 17 from # 9 (www.qq.com)
Response 22 from # 5 (www.baidu.com)
Response 23 from # 27 (www.163.com)
Response 24 from # 14 (www.taobao.com)
Response 18 from # 5 (www.baidu.com)
Response 19 from # 14 (www.taobao.com)
Response 25 from # 24 (www.google.co.jp)
Response 26 from # 30 (www.flickr.com)
Response 20 from # 29 (www.googleusercontent.com)
Response 21 from # 22 (www.yandex.ru)
Response 27 from # 23 (www.ebay.com)
Response 22 from # 19 (www.google.de)
Response 23 from # 21 (www.google.co.uk)
Response 24 from # 28 (www.google.com.br)
Response 25 from # 25 (www.microsoft.com)
Response 26 from # 20 (www.bing.com)
Response 27 from # 30 (www.flickr.com)
Response 28 from # 22 (www.yandex.ru)
Response 28 from # 27 (www.163.com)
Response 29 from # 25 (www.microsoft.com)
Response 29 from # 26 (www.google.fr)
Response 30 from # 21 (www.google.co.uk)
Response 30 from # 23 (www.ebay.com)
Got a connection.
But returning because the path was not '/'
Como se puede ver, que no sea el período de tiempo que me llevó a golpear Alt+Tab Enter
, las devoluciones de llamada están completamente entremezclados - asíncrona, sin bloqueo de E/S en su máxima expresión.
[Editar]
Como mtomis mencionados, el número máximo de conexiones que puede tener abiertos por host es configurable a través del mundial http.globalAgent.maxSockets
. Simplemente configure esto como el número de conexiones simultáneas que desea controlar por host, y el problema que observó desaparece.
También vale la pena señalar que, además de ser capaz de configurar 'httpGlobalAgent.maxSockets' como un entero más grande (como se especifica en varias respuestas), también puede establecerlo en' Infinity' para eliminar los límites por completo. – skeggse