I have the following simple http server using Node.js:
var http = require('http');
var server = http.createServer(function(req, res) {
var counter = 0;
for(var i = 1; i <= 30; i++) {
http.get({ host: "www.google.com" }, function(r) {
counter++;
res.write("Response " + counter + ": " + r.statusCode + "\n");
if(counter == 30) res.end();
});
}
});
server.listen(8000);
When I curl into my local host on port 8000, I do get the expected result of:
Response 1: 200
Response 2: 200
Response 3: 200
...
Response 30: 200
But when I try to curl in from another terminal while the first process is running, I see the console hang and wait for the first process to finish entirely before it starts receiving the same output.
My understanding was that since this is async code using callbacks that node could handle multiple requests in sync by processing them on the next tick of the event loop. And in fact I even watched a video of Ryan Dahl doing something similar with a hello world example. What’s in my code that’s making the server block?
Your issue doesn’t have anything to do with blocking calls; this has to do with the fact that you are only able to open a certain number of connections at a time to a single host. Once you hit the maximum number of open connections, the other asynchronous calls to
http.gethave to wait until the number of open connections falls again, which happens when the other requests are complete and their callbacks are fired. Since you’re creating new requests faster than they drain, you get your seemingly blocking results.Here is a modified version of your program I created to test this. (Note that there is an easier way to solve your problem, as indicated by mtomis–more on this below.) I added some
console.loglogging, so it is easier to tell what order things were being processed in; I also reject all requests for anything other than/, so thatfavicon.icorequests are ignored. Finally, I make requests to many various websites.I ran this program and very quickly visited the page in two different browsers (I also flushed my DNS cache, as the test was running too quickly to get good output otherwise). Here is the output:
As you can see, other than the period of time it took me to hit
Alt+Tab Enter, the callbacks are completely intermingled–asynchronous, non-blocking I/O at its finest.[Edit]
As mtomis mentioned, the number of maximum connections you can have open per host is configurable via the global
http.globalAgent.maxSockets. Simply set this to the number of concurrent connections you want to be able to handle per host, and the issue you observed disappears.