当前位置: 首页 > 面试题库 >

单线程无阻塞IO模型在Node.js中的工作方式

柳景胜
2023-03-14
问题内容

我不是Node程序员,但我对 单线程无阻塞IO模型的
工作方式感兴趣。在阅读了理解理解节点事件循环文章之后,我对此感到非常困惑。它给出了该模型的示例:

c.query(
   'SELECT SLEEP(20);',
   function (err, results, fields) {
     if (err) {
       throw err;
     }
     res.writeHead(200, {'Content-Type': 'text/html'});
     res.end('<html><head><title>Hello</title></head><body><h1>Return from async DB query</h1></body></html>');
     c.end();
    }
);

队列: 由于只有一个线程,所以有两个请求A(首先出现)和B(首先出现),服务器端程序将首先处理请求A:执行SQL查询是代表I /
O等待的sleeping语句。并且该程序被困在I/O等待中,并且无法执行使网页落后的代码。在等待期间程序会切换到请求B吗?我认为,由于是单线程模型,因此无法将一个请求从另一个请求中切换出来。但是示例代码的标题表明,
除了您的代码之外所有其他内容都可以并行运行

(由于我从没使用过Node,所以我不确定我是否会误解代码。)在等待期间,Node如何将A切换到B?您能否以简单的方式解释Node的
单线程无阻塞IO模型 ?如果您能帮助我,我将不胜感激。:)


问题答案:

Node.js建立在libuv上,libuv是一个跨平台的库,它为支持的操作系统(至少为Unix,OS
X和Windows)提供的异步(非阻塞)输入/输出抽象api / syscall。

异步IO

在此编程模型中,对由文件系统管理的设备和资源(套接字,文件系统等)的打开/读取/写入操作 不会阻塞调用线程
(如在典型的类似c的同步模型中),而只是标记新数据或事件可用时,将通知进程(在内核/
OS级数据结构中)。如果是类似Web服务器的应用程序,则该过程负责确定通知事件属于哪个请求/上下文,并从那里继续处理请求。请注意,这必然意味着您将与向OS发起请求的堆栈位于不同的堆栈框架上,因为OS必须屈服于进程的调度程序才能使单线程进程处理新事件。

我描述的模型的问题在于,它对程序员不熟悉并且很难推理,因为它本质上是非顺序的。“您需要在函数A中发出请求,并在另一个函数中处理结果,而通常情况下,您无法使用A中的本地人。

节点的模型(继续传递样式和事件循环)

Node通过诱使程序员采用某种编程风格,利用javascript的语言功能解决了该问题,使该模型看起来更具同步性。每个请求IO的功能都具有类似的签名,function (... parameters ..., callback)并且需要给其提供一个回调,该回调将在请求的操作完成时被调用(请注意,大部分时间都在等待OS发出完成信号,这是可以花费的时间)。花了其他工作)。Javascript对闭包的支持使您可以使用在回调主体内的外部(调用)函数中定义的变量-
这样可以保留节点运行时将独立调用的不同函数之间的状态。另请参见继续传递样式。

而且,在调用产生了IO操作的函数之后,调用函数通常将return控制到节点的 事件循环
。该循环将调用计划执行的下一个回调或函数(很可能是因为相应的事件已由OS通知)-这允许并发处理多个请求。

您可以认为节点的事件循环 有点类似于内核的调度程序 :内核将在其未完成的IO完成后调度执行阻塞的线程,而节点将在发生相应事件时调度回调。

高度并发,无并行

最后,短语“除了代码之外的所有内容并行运行”在捕捉节点允许您的代码通过多路复用和排序所有js并发处理 单个线程 同时处理来自 成千上万个开放套接字的
请求这一点上做得不错单个执行流中的逻辑(即使说“一切并行运行”在这里可能不正确-。这对于webapp服务器非常有效,因为实际上大部分时间都花在等待网络或磁盘(数据库/套接字)上,并且逻辑实际上并不占用CPU过多的资源-也就是说: 这对于IO绑定的工作负载非常有效



 类似资料:
  • 我不是节点程序员,但我对单线程非阻塞IO模型如何工作感兴趣。在我阅读了理解-the-node-js-event-loop这篇文章之后,我对它真的很困惑。它给出了一个模型的例子: QUE:由于只有一个线程,当有两个请求A(先来)和B时,服务器端程序将首先处理请求A:做SQL查询是sleep语句,代表I/O wait。并且程序被堆放在等待中,无法执行在后面呈现web页面的代码。在等待期间程序会切换到请

  • 我有4-5个工作线程处理大型消息队列。我还有另一段代码,它使用2-3个worker运行。我想在处理大型消息队列时阻止所有其他工作者。 我正在使用JDK6和Jms 编辑: 队列进程工作者从未终止。当没有消息时,它们阻塞队列。这些工作者由执行器线程池管理,如果我使用读写锁,其中一个工作者也会被阻塞。此外,如果使用循环屏障,那么我必须终止线程,以便重新传递阻塞的第二个进程。由于工作者是由线程池管理的,所

  • 问题内容: Node.JS的最大优点是它具有非阻塞性。它是单线程的,因此不需要为每个新的传入连接生成新的线程。 在事件循环(实际上是单线程)的后面,有一个“非阻塞工作程序”。这个东西不再是单线程的,所以(据我了解),它可以为每个任务产生一个新线程。 也许我误会了一些东西,但是优势到底在哪里。如果要处理的任务很多,那么“非阻塞工作”会不会变成“阻塞工作人员”? 谢谢克里斯蒂安 问题答案: 您需要阅读

  • 我有一个vert。x标准Verticle基本上,它解析HttpRequest并准备JsonObject,然后我通过事件总线发送JsonObject。在另一个Worker verticale中,该事件被消耗,并将启动执行(包括对Penthao数据集成Java API的调用),它正在阻止API。完成“.kjb”文件的执行大约需要30分钟。但是vert。x不断警告Worker线程块,所以我的问题是ver

  • 在Java中,线程可以有不同的状态: 新建、可运行、阻止、等待、定时等待、终止 但是,当线程被IO阻塞时,其状态为“RUNNABLE”。我如何判断它是否被IO阻止?

  • 问题内容: 我有一个在后台运行的线程正在以阻塞方式从输入设备读取事件,现在当我退出应用程序时,我想正确清理线程,但是我不能只运行pthread_join(),因为该线程由于IO阻塞而永远不会退出。 我如何正确解决这种情况?我应该发送一个pthread_kill(theard,SIGIORM)还是一个pthread_kill(theard,SIGALRM)来中断该块?那两个信号是否正确?还是有另一种