Reputation: 2783
Take this code, typical node js example of a Http server, to which I've added a delay of 5 seconds to simulate some async work taking place somewhere else:
const http = require('http');
const hostname = '127.0.0.1';
const port = 8080;
http.createServer((req, res) => {
setTimeout(()=>{
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
},5000);
}).listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
What I would expect is that when I open 5 tabs, let's say with a delay of half a second between opening each, the server should "respond" to each tab more or less with this timings:
t=0s - I open first tab
t=0.5s - I open second tab
t=1s - I open third tab
...
t=5s - First tab stops loading, server has replied
t=5.5s - Second tab stops loading, server has replied
t=6s - Third tab stops loading, server has replied
t=6.5s - Fourth tab stops loading, server has replied
t=7s - Fifth tab stops loading, server has replied
However, the behaviour I'm seeing is the following:
t=0s - I open first tab
t=0.5s - I open second tab
t=1s - I open third tab
...
t=5s - First tab stops loading, server has replied
t=10s - Second tab stops loading, server has replied
t=15s - Third tab stops loading, server has replied
t=20s - Fourth tab stops loading, server has replied
t=25s - Fifth tab stops loading, server has replied
As if the subsequent requests weren't starting to run until the first one has finished. Am I missing something here? I thought the whole point of Node JS was to be able to run async taks from a single thread?
Upvotes: 16
Views: 1014
Reputation: 35700
Seems this only happens in some browsers, I tried with safari, and it works as expected. So I guess that Chrome would limit the number of same requests to the same resource at the same time
Upvotes: 5
Reputation: 37822
The problem isn't your code or Node.js -- it's how you set up your test.
You wrongly assumed that your browser would make 5 concurrent requests, which is not happening. Different browsers have different behaviors, but typically browsers limit to a very low number the maximum amount of simultaneous connections to a single origin. The HTTP spec gives a suggest maximum. I was actually quite surprised to see Chrome only opening 1 single connection to localhost, as I know Chrome opens 6 to other origins -- just learned something new!
Use a different tool to run your test, one that you can control and know for sure that it's making concurrent requests. Then you'll see the expected behavior.
As an example, I ran your code and tested with Apache Benchmark as shown below. The parameters indicate: -n 10
is to make 10 requests, -c 10
is to use concurrency 10 (ie, make all the ten requests concurrently). As you can see in the results below, the total time taken for all the requests was ~5s (and "time per request" 0.5s):
~ $ ab -n 10 -c 10 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1663405 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient).....done
Server Software:
Server Hostname: 127.0.0.1
Server Port: 8080
Document Path: /
Document Length: 12 bytes
Concurrency Level: 10
Time taken for tests: 5.019 seconds
Complete requests: 10
Failed requests: 0
Total transferred: 1130 bytes
HTML transferred: 120 bytes
Requests per second: 1.99 [#/sec] (mean)
Time per request: 5019.151 [ms] (mean)
Time per request: 501.915 [ms] (mean, across all concurrent requests)
Transfer rate: 0.22 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 0
Processing: 5017 5018 0.3 5018 5018
Waiting: 5008 5008 0.2 5008 5009
Total: 5018 5018 0.2 5019 5019
ERROR: The median and mean for the total time are more than twice the standard
deviation apart. These results are NOT reliable.
Percentage of the requests served within a certain time (ms)
50% 5019
66% 5019
75% 5019
80% 5019
90% 5019
95% 5019
98% 5019
99% 5019
100% 5019 (longest request)
Upvotes: 21