【问题标题】:How does node.js/libuv support async io using the reactor patternnode.js/libuv如何使用reactor模式支持异步io
【发布时间】:2017-12-26 00:52:15
【问题描述】:

libuv 用于处理 IO 的反应器模式在设计上是同步的,但 libuv 支持异步 io。这怎么可能? libuv 是否以某种方式扩展了反应器的设计以支持异步 io?使用多个线程/事件循环是否有助于实现这一点?

【问题讨论】:

    标签: node.js asynchronous io libuv reactor


    【解决方案1】:

    Node 和 libuv 的 I/O 模型和 Nginx 内部做的非常相似。

    libuv 使用单线程事件循环和非阻塞异步 I/O。所有函数都是同步的,它们会运行到完成,但是可以使用一些聪明的 promises 和 generators 来表现它们不同步(事实上,生成器函数的调用都是非阻塞的并返回生成器对象立即和像.next()这样的生成器方法运行完成),加上新的异步/等待语法使其非常方便。

    对于无法以非阻塞方式完成的操作,Node 使用线程池在单独的线程中运行阻塞操作,但这是透明地完成的,它永远不会暴露给用 JavaScript 编写的应用程序代码(您需要逐步直到 C++ 直接使用它)。

    见:http://docs.libuv.org/en/v1.x/design.html

    与网络 I/O 不同,libuv 没有可以依赖的特定于平台的文件 I/O 原语,因此当前的方法是在线程池中运行阻塞文件 I/O 操作。 [...]

    libuv 当前使用一个全局线程池,所有循环都可以在其中排队工作。目前在此池上运行 3 种类型的操作:

    • 文件系统操作
    • DNS 函数(getaddrinfo 和 getnameinfo)
    • 用户通过 uv_queue_work() 指定代码

    有关更多详细信息,另请参阅这些答案:

    请参阅这些答案中的链接和插图。有很多关于该主题的资源可供阅读。

    【讨论】:

    • 这些都是很好的参考,但没有一个专门讨论这个问题。让我问一个更具体的问题。由于所有网络 io 都在 libuv 中的单个线程上运行,例如,要通过读取事件来实现异步 io,您必须为操作系统委派任务并为其提供用户定义的缓冲区,该缓冲区将填充来自阅读操作,但这将是前摄器模式。 libuv如何通过使用单线程reactor事件循环来达到类似的效果?
    • @Michael 大多数网络 I/O 运行在单个 therad 但例如不是 DNS 操作(getaddrinfo 和 getnameinfo),也不是文件系统 I/O,所以这并不像看起来那样清晰,并且没有单一的理论模式可以 100% 应用于 Node 需要的所有边缘情况支持所有平台。
    • @Michael 我在答案中包含的列表中的第一个答案有一些您可能会发现有用的 cmets 由 saghul 发布(我想他会给您一个更详细的评论答案在这里,但不幸的是,只能@-提及 cmets 中的某个人来回答他已经评论过的地方)。
    猜你喜欢
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    相关资源
    最近更新 更多