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

标签 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”,但它仅在第一个选项卡中收到响应后才打印。

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

我在这里想了解什么?如何修复此行为?

最佳答案

What am i missing here to understand?

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

如果您可以在客户端或服务器计算机上运行某种网络 spy ,您可以验证发送第二个 http 请求的精确时间,但我很确定您会发现浏览器在第一个请求完成之前不会发送它。

我可以想到浏览器可能这样做的三个可能原因:

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

How can this behavior be fixed?

在不久前的测试中,我可以通过向第二个请求添加查询字符串(例如 http://localhost:3000?num=2)来解决这个问题。这使得它成为与第一个请求“不同”的请求,并且浏览器没有阻止它。您必须确保您的服务器仍在处理请求,即使它上面有查询字符串。

在 Chrome 中进行一些测试

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

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

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

关于node.js - Nodejs服务器如何处理来自同一客户端和不同客户端的多个并发请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60034880/

相关文章:

node.js - TypeError : callback. apply 不是allowDiskUse之后的函数

node.js - 如何链接两个docker容器?

node.js - 为什么下载文件会产生 EADDRNOTAVAIL 错误?

node.js - 重新发布 - 错误 : Ident authentication failed for user

javascript - NodeJs Testrunner 在设置 Express 服务器时卡住/停止

javascript - 使用 Grunt (Yeoman) 的多个构建文件夹(多个客户端、多任务、多个目标)

node.js - 使用一个 Angular 7 应用程序的多个域和子域

javascript - 我可以在服务器端使用某些客户端 Javascript API 吗?

javascript - 在第二个请求中使用 oauth token - NODEJS

performance - nodejs http 和 redis,只有 6000req/s