nodejs服务器如何处理来自同一客户端和不同客户端的多个并发请求?

时间:2020-02-03 07:32:46

标签: node.js

我正在测试以下代码:

const http = require('http');

const server = http.createServer((req, res)=> {

    const url = req.url;

    if(url === '/'){
        setTimeout(() => {
            res.write('<html>');
            res.write('<head><title>Enter Message</title></head>');
            res.write('<body><form action="/message" method="POST"><input type="text" name="message"><button type="submit">Send</button></form></body>');
            res.write('</html>');

            return res.end();

        }, 10000);

        console.log('Hi');
    }
});

server.listen(3000);

场景1:我要做的是打开浏览器窗口并运行localhost:3000,立即打印Hi,并在浏览器中收到10秒钟响应,与此同时(在控制台打印Hi和在浏览器选项卡中收到响应之间) ),我打开一个不同的浏览器选项卡,然后再次转到loaclhost:3000,我希望再次打印“ Hi”,但是只有在第一个选项卡中收到响应后才打印“ Hi”。

场景2:我重复上述操作,但是在同一浏览器窗口中打开第二个选项卡的地方,我选择以隐身模式或在与笔记本电脑相同网络中的设备上打开它,然后我看不到任何延迟,立即为incongnito窗口中的请求打印Hi,而第一个浏览器的响应仍要收到吗?

我在这里想了解什么?如何解决此问题?

1 个答案:

答案 0 :(得分:3)

我在这里想了解什么?

这是由浏览器而不是node.js引起的,并且是浏览器的实现细节。浏览器显然正在决定,如果已经在处理http://localhost:3000的请求,它将不会发送另一个相同的请求,直到该请求完成为止。您已验证使用其他浏览器会使问题消失,这与浏览器实现问题/功能一致。此外,由于正在使用setTimeout(),因此node.js中没有任何行为会导致此问题,因此node.js当然可以自由地开始处理第二个请求(如果到达)。

如果您可以在客户端或服务器计算机上运行某种网络间谍,则可以验证发送第二个HTTP请求的确切时间,但是我敢肯定,您会发现浏览器没有发送直到第一个请求完成。

我可以想到浏览器执行此操作的三个可能原因:

  1. 浏览器已经可以立即打开对该主机的最大请求数。每个浏览器都配置了一次最多可向同一主机发送的请求,但是该限制绝对不止一个,因此,必须有对该主机的其他打开的请求,这才是原因。
  2. 浏览器判断服务器是否对特定请求的响应速度慢,那么这将无法帮助该服务器更快地发送另一个相同的请求。
  3. 浏览器希望第一个结果可能是可缓存的,因此当它返回时,浏览器可能只能将该结果用于第二个请求。

如何解决此问题?

前段时间的先前测试中,我可以通过向第二个请求(例如http://localhost:3000?num=2)添加查询字符串来解决该问题,这使它与第一个请求“不同”,浏览器没有不要退缩。即使服务器上有查询字符串,也必须确保服务器仍在处理请求。

在Chrome中进行了一些测试

然后,使用服务器代码的一种变体来剥离查询字符串,以使其不受此影响,我已经验证了Chrome,如果两个浏览器都将推迟发送第二个请求,直到第一个请求完成窗口具有完全相同的URL,但是将查询字符串添加到第二个窗口将导致两个窗口立即发送,这是可能的解决方法。

在Firefox中进行测试会产生不同的结果

作为更多证据表明这与node.js本身无关,如果我在Firefox中重复相同的测试,则没有这种行为。在两个单独的窗口中,两个相同的请求都一个接一个地发送到node.js,我立即看到两个console.log("Hi")语句。

相关问题