具有多个并发请求的Node.js服务器,它如何工作?

悉达思

我知道node.js是单线程,异步,无阻塞的I / O。我已经读了很多。例如,PHP每个请求使用一个线程,但是节点仅对所有线程使用一个线程。

假设有三个请求a,b,c同时到达node.js服务器。这些请求中的三个需要大型阻止操作,例如,它们都希望读取相同的大文件。

然后,如何将请求排入队列,将按什么顺序执行阻塞操作,以及按什么顺序分派响应?当然要用多少个线程?

请告诉我三个请求从请求到响应的顺序。

jfriend00

这是针对您的三个请求的事件序列的描述:

  1. 三个请求被发送到node.js Web服务器。
  2. 无论哪一个请求在其他两个请求之前到达,都会触发Web服务器请求处理程序并开始执行。
  3. 其他两个请求进入node.js事件队列,等待轮到他们。从技术上讲,是否将等待的请求排队在传入的TCP级别上,还是将它排队在node.js内部(我实际上不知道),这完全取决于node.js实现的内部,但是出于讨论的目的,所有重要的是,传入事件已排队,直到第一个请求停止运行时才触发。
  4. 该第一个请求处理程序将一直执行到遇到异步操作(例如读取文件)为止,然后再无其他操作,直到异步操作完成为止。
  5. 此时,异步文件I / O操作将启动,并且原始请求处理程序将返回(已完成其当时的操作)。
  6. 由于第一个请求(正在等待文件I / O)现在已经返回,因此node.js引擎现在可以将下一个事件从事件队列中拉出并启动它。这是到达服务器的第二个请求。它将在第一个请求时经历相同的过程,并将一直运行直到无其他事情为止(并且还在等待文件I / O)。
  7. 当第二个请求返回系统时(因为它正在等待文件I / O),则第三个请求可以开始运行。它将遵循与前两个相同的路径。
  8. 现在,当第三个请求也正在等待I / O并返回系统时,node.js可以自由地将下一个事件从事件队列中拉出。
  9. 此时,所有三个请求处理程序都同时处于“运行中”状态。实际上一次只能运行一次,但是所有一次都可以运行。
  10. 事件队列中的下一个事件可能是某个其他事件或某个其他请求,也可能是前三个文件I / O操作之一的完成。队列中下一个事件将开始执行。假设它是第一个请求的文件I / O操作。此时,它调用与该第一个请求的文件I / O操作相关的完成回调,并且该第一个请求开始处理文件I / O结果。然后,该代码将继续运行,直到完成整个请求并返回,或者开始其他异步操作(如更多文件I / O)并返回为止。
  11. 最终,第二个请求的文件I / O将准备就绪,该事件将从事件队列中拉出。
  12. 然后,对第三个请求相同,最终所有三个请求都将完成。

因此,即使实际上只有一个请求实际上同时在执行,多个请求也可以同时处于“处理中”或“运行中”状态。有时这称为协作多任务,而不是通过具有多个本机线程的“抢先”多任务,系统可以随时在这些线程之间自由切换,给定的Javascript线程运行直到返回系统,然后再返回,只有这样,才能开始运行另一段Javascript。因为一段Javascript可以启动非阻塞异步操作,所以Javascript线程可以在其异步操作仍处于挂起状态时返回到系统(使其他Javascript片段可以运行)。这些操作完成后,

单螺纹

这里的关键点是,给定的Javascript线程将一直运行,直到它返回系统为止。如果在执行过程中启动了一些异步操作(例如文件I / O或网络连接),那么当这些事件结束时,它们会将一个事件放入事件队列中,并且当JS引擎完成运行任何事件之前,它将为该事件提供服务,并导致调用回调,并且该回调将轮流执行。

与多线程模型相比,这种单线程性质极大地简化了并发的处理方式。在每个请求都启动其自己的线程的完全多线程环境中,任何希望共享的数据,甚至是一个简单的变量,都必须遵守竞争条件,并且必须使用互斥体进行保护,然后任何人才能读取它。

在Javascript中,因为没有多个请求的并发执行,所以对于简单的共享变量访问不需要互斥体。根据定义,此时一段Javascript正在读取一个变量,此时没有其他Javascript在运行(单线程)。

Node.js确实使用线程

注意的一种技术区别是,只有Javascript的执行是单线程的。node.js内部构件确实将线程本身用于某些方面。例如,异步文件I / O实际上使用本机线程。网络I / O实际上并不使用线程(它使用本机事件驱动的网络)。

但是,在node.js内部使用线程不会直接影响Javascript执行。一次只能执行一个Java线程。

比赛条件

启动异步操作时,在修改状态的过程中仍可能存在争用条件,但是这种方法比多线程环境中的方法少见,并且更容易识别和保护这些情况。作为可能存在的竞争条件的示例,我有一个简单的服务器,该服务器使用间隔计时器每10秒从多个温度探测器获取读数。它从所有这些温度读数中收集数据,并且每小时将其写出到磁盘。它使用异步I / O将数据写入磁盘。但是,由于使用了许多不同的异步文件I / O操作将数据写入磁盘,因此间隔计时器可能会在某些异步文件I / O操作之间触发,从而导致服务器所在的数据写入磁盘的中间要修改。这很不好,可能导致写入不一致的数据。在一个简单的世界中,可以通过在开始将所有数据写入磁盘之前对其进行复制来避免这种情况,因此,如果在将数据写入磁盘时出现新的温度读数,则该副本将不会受到影响,并且代码仍将一致的数据集写入磁盘。但是,对于这种服务器,数据可能很大,而服务器上的内存却很小(这是Raspberry Pi服务器),因此在内存中复制所有数据是不切实际的。副本将不受影响,并且代码仍将一致的数据集写入磁盘。但是,对于这种服务器,数据可能很大,而服务器上的内存却很小(这是Raspberry Pi服务器),因此在内存中复制所有数据是不切实际的。副本将不受影响,并且代码仍将一致的数据集写入磁盘。但是,对于这种服务器,数据可能很大,而服务器上的内存却很小(这是Raspberry Pi服务器),因此在内存中复制所有数据是不切实际的。

因此,可以通过在将数据写入磁盘的过程中设置一个标志,然后在将数据写入磁盘后清除该标志来解决该问题。如果在设置此标志时触发间隔计时器,则会将新数据放入单独的队列中,并且不会修改正在写入磁盘的核心数据。将数据写入磁盘后,它将检查队列并将找到的任何温度数据添加到内存中的温度数据中。保留了正在写入磁盘的过程的完整性。每当此“竞赛条件”被击中并且由于该原因数据进入队列时,我的服务器都会记录一个事件。而且,瞧,它确实每隔一段时间就会发生一次,并且保存数据完整性的代码也起作用了。

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

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

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

node.js服务器如何将并发请求排队

当同时有500多个请求到服务器时,如何在mysql中实现并发

Node.js 服务器同时处理多个请求

如何运行多个js服务器

如何修复对Node.js服务器的提取请求?

Node.js服务器如何处理请求?

如何跨多个服务器/工作器管理WebSocket

具有多个积压的服务器套接字如何工作?

Node.js 服务器突然无法工作

Node js REST 无法使用快速服务器工作

Node.js:使用IPC在主服务器和工作服务器之间进行请求/响应

服务器如何发送消息 SSE 在多个服务器实例环境中工作

如何允许 Node.js 服务器接受 Ubuntu 上的所有请求?

首选和备用或多个DNS服务器如何工作?

Node.js mssql 到 SQL 服务器的多个并发连接相互干扰

Node.js区分http请求;具有相同公共IP的多个设备

Node.js-WebSocket节点模块:如何使多客户端套接字服务器正常工作?

node.js http服务器并发问题

当响应是异步的时,Node.js 中如何处理多个并发请求?

如何在在线服务器上启动Node JS服务器?

Node.js服务器(如Express)如何管理内存而不是PHP服务器?

如何从Firebase服务器启动Node.js服务器?

如何将本地服务器转换为在线服务器 Node.js

Nodejs处理的并发请求如何表达http服务器?

具有多个服务器的JPA

具有多个服务器的Prometheus

Node.js-如何充当Modbus RTU服务器

如何获取运行node.js的服务器名称?

Node.js如何处理服务器的下拉?