【问题标题】:How non-blocking I/O works with channels非阻塞 I/O 如何与通道一起使用
【发布时间】:2018-10-18 17:53:05
【问题描述】:

我想知道 node.js 中的引擎如何知道何时调用和执行排队操作。我理解node.js是单线程的,使用异步非阻塞来执行操作。

但是,假设您正在从数据库调用某些内容,并且 node.js 将操作排队,并且不等待它执行更多的代码行。作为单线程,它将数据存储在通道中(如果我没记错的话)。但是服务器怎么知道网络不忙,是时候执行排队操作了。

或者它在程序结束时执行排队的操作。这不可能。所以我很想知道幕后发生了什么以及节点服务器如何知道何时执行排队操作。

【问题讨论】:

  • 当你说“有频道”时,你到底在说什么? “通道”不是已知的 node.js 概念,因此我们需要知道您的意思。
  • 从我在互联网上看到的,非阻塞 IO 与通道一起工作,线程可以在通道中读取/写入一条数据,而不会阻塞其余数据的 IO
  • node.js 中没有“通道”的概念——至少这不是 node.js 在任何地方使用的术语。不知道你是在哪里读到的,也不知道它们是什么意思。
  • tutorials.jenkov.com/java-nio/nio-vs-io.html。阅读它听到它在阻塞与非阻塞部分中说“线程可以请求将一些数据写入通道”
  • 该教程是在讨论 Java,而不是 Javascript。与 node.js 完全无关。

标签: node.js asynchronous nonblocking serverside-javascript


【解决方案1】:

不清楚您所说的“通道”是什么意思,因为它不是 node.js 的内置概念,也不是内部用来描述 node.js 工作方式的术语。您评论中的tutorial you reference 是在谈论Java 语言,而不是Javascript 语言,因此它与node.js 绝对无关。该教程中的“通道”概念是特定 NIO 库在 Java 中实现的。

但是,如果你真的只是问异步操作在 node.js 中是如何工作的,我可以解释一下这个笼统的概念。

node.js 使用事件队列。 node.js 解释器抓取事件队列中的下一个事件并执行它(通常涉及调用回调函数)。该回调函数运行(单线程)直到它返回。当它返回时,node.js 解释器然后在事件队列中查找下一个事件。如果有,它会抓取下一个事件并调用与之关联的回调。如果事件队列中当前没有事件,则等待将事件放入事件队列(无事可做可能会运行一些垃圾收集)。

现在,当您在 Javascript 中运行某种异步操作(例如数据库查询)时,您可以使用 db 查询函数来启动查询(通过将查询发送到数据库)然后立即返回。这允许您启动该查询的 Javascript 然后返回并将控制权交还给 node.js。

与此同时,一些本机代码正在管理与您的数据库的连接。当响应从数据库返回时,一个事件被添加到内部 node.js 事件队列中。

每当 node.js 解释器完成运行其他 Javascript 时,它就会查看事件队列并拉出下一个事件并调用与之关联的回调。这样,您的数据库查询结果将由您的代码处理。在此处的所有情况下,异步操作都有某种与之关联的回调,解释器在事件队列中找到事件时可以调用该回调。

作为单线程,它将数据存储在通道中(如果我没记错的话)。

node.js 没有“通道”概念,所以我不确定你的意思。

或者它在程序结束时执行排队的操作。

当结果从数据库返回时,一些本地代码管理会将事件插入到 node.js 事件队列中。 Javascript 解释器将为该事件提供服务,然后在下次返回事件循环时(其他 Javascript 已完成运行,是时候检查下一个要处理的事件了)。

了解启动异步操作是非阻塞的很重要,因此您会得到以下信息:

console.log("1");
callSomeAsyncFunction(someData, (err, data) => {
    // this callback gets called later when the async operation finishes
    // and node.js gets a chance to process the event that was put
    // in the event queue by the code that managed the async operation
    console.log("2");
});

// right here there is nothing else to do so the interpreter returns back
// to the system, allowing it to process other events
console.log("3");

由于事物的非阻塞性质,这将记录:

1
3
2

关于该主题的其他一些参考资料:

How does JavaScript handle AJAX responses in the background?

Where is the node.js event queue?

Understanding Call backs

Why does a while loop block the node event loop?

【讨论】:

  • 事件队列和调用栈一样
  • @Duck_dragon - 不。调用堆栈非常不同。事件队列是等待调用其回调的事件的文字队列。
  • @Duck_dragon - 用您引用的特定库/教程的一些信息更新了我的答案。
  • 我一定会看看你提供的资源。谢谢。事件队列是指任务队列,事件从那里检查调用 satck 是否为空,然后将其从事件队列放入调用堆栈以执行。
  • @Duck_dragon - 调用堆栈用于跟踪函数调用和管理函数返回。当事件的回调完成运行时,最后一个函数return 将返回到最初调用的事件循环子系统。此时调用堆栈为空,系统知道前一个事件已执行完毕,node.js 可以获取下一个事件并调用其回调。没有“检查调用堆栈是否为空”。当事件回调返回到事件子系统时,调用堆栈根据定义此时为空。
【解决方案2】:

Node 内部使用底层操作系统非阻塞 io API-s。请参阅overlapped ioWSAEventSelect(适用于 Windows)、select(适用于 Linux)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    • 1970-01-01
    • 2020-05-24
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多