单线程Node.js如何同时处理请求?

长路

我目前正在深入学习Nodejs平台。众所周知,Nodejs是单线程的,并且如果它执行阻塞操作(例如fs.readFileSync),则线程应等待完成该操作。我决定做一个实验:我创建了一个服务器,该服务器在每次请求时都使用文件中的大量数据进行响应

const { createServer } = require('http');
const fs = require('fs');

const server = createServer();

server.on('request', (req, res) => {
    let data;
    data =fs.readFileSync('./big.file');
    res.end(data);
});

server.listen(8000);

另外,为了启动对服务器的并行请求,我启动了5个终端。我等待看到正在处理一个请求时,其他请求则应等待从第一个请求完成阻塞操作。但是,其他4个请求被同时响应。为什么会发生这种现象?

jfriend00

您可能看到的是要么实现内部的异步部分res.end()以实际发送大量数据,要么看到所有数据都非常快速且串行地发送,但是客户端无法足够快地处理它,而实际上依次显示它,并且由于客户端各自处于各自独立的过程中,因此它们“出现”以显示它是同时到达的,这仅仅是因为它们反应太慢而无法显示实际到达的顺序。

人们将不得不使用网络嗅探器来查看其中哪一个实际上正在发生,或者运行一些不同的测试,或者res.end()在客户端的TCP堆栈的实现中放入一些日志记录,或者在客户端的TCP堆栈中利用某些日志记录来确定不同分组之间数据包到达的实际顺序。要求。


如果您有一台服务器,并且它有一个正在执行同步I / O的请求处理程序,那么您将不会同时获得多个请求进程。如果您相信这种情况正在发生,那么您将必须准确记录如何衡量或得出结论(以便我们可以帮助您消除误解),因为在使用阻塞式同步I / O时,node.js的工作方式并非如此。作为fs.readFileSync()

node.js以单线程方式运行JS,并且当您使用阻塞的同步I / O时,它将阻塞Javascript的一个线程。这就是为什么永远不要在服务器中使用同步I / O的原因,除非在启动代码中仅在启动期间运行一次。

清楚的是,这fs.readFileSync('./big.file')是同步的,因此您的第二个请求在第一个请求fs.readFileSync()完成之前不会开始处理而且,一次又一次地在同一文件上调用它会非常快(OS磁盘缓存)。

但是,res.end(data)是非阻塞,异步的。res是一个流,您正在为流提供一些要处理的数据。它会通过套接字发送尽可能多的内容,但是如果它受到TCP的流控制,它将暂停直到在套接字上有更多的发送空间。发生多少取决于计算机的各种情况,它的配置以及到客户端的网络链接。

因此,可能会发生以下事件序列:

  1. 第一个请求到达并执行fs.readFileSync()并调用res.end(data)这开始将数据发送到客户端,但是由于TCP流量控制而在完成之前返回。这会将node.js发送回其事件循环。

  2. 第二个请求到达并执行fs.readFileSync()并调用res.end(data)这开始将数据发送到客户端,但是由于TCP流量控制而在完成之前返回。这会将node.js发送回其事件循环。

  3. 此时,事件循环可能会开始处理第三个或第四个请求,或者可能会处理更多事件(从res.end()第一个请求的实现内部或writeStream的内部继续发送更多数据。如果确实为那些事件提供服务,则可能(从客户端的角度出发,给出不同请求真正并发的外观)。

另外,客户端可能导致其显示为已排序。每个客户端都在读取一个不同的缓冲套接字,如果它们都在不同的终端中,则它们是多任务的。因此,如果每个客户端套接字上的数据多于其立即读取和显示的数据(可能是这种情况),则每个客户端将读取一些内容,显示一些内容,读取更多内容,显示更多内容,等等。在服务器上发送每个客户端的响应之间的延迟小于在客户端上读取和显示的延迟,然后客户端(每个客户端在各自独立的进程中)可以并发运行。


当您使用异步I / O(例如)时fs.readFile(),正确编写的node.js Javascript代码可以同时“运行”许多请求。它们实际上并不会在完全相同的时间并发运行,但是可以运行,执行一些工作,启动异步操作,然后让其运行另一个请求。使用正确编写的异步I / O,即使在请求处理程序等待异步I / O请求完成时,它也更像是共享单个线程,这从外部世界看似乎并发处理。但是,您显示的服务器代码不是此协作的异步I / O。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章