Node.js内部机制:它是如何工作的?

17

也许实现node.js模块的某个人可以解释一下单线程处理的node.js队列和模块执行的阻塞IO操作之间的协议。

我怀疑它可能是这样的:

  1. node.js线程以闭包形式注册回调函数,并将其与某些关联ID一起保存。
  2. node.js在模块上调用一个方法(应该执行阻塞IO),并将方法参数和关联ID传递给它。
  3. 模块方法开启一个线程并在IO操作上进行阻塞。
  4. 当IO操作完成时,模块的线程会回调node.js线程,并将结果和关联ID传递给它。
  5. node.js线程通过关联ID找到存储的回调闭包,并使用从模块返回的结果调用它。

问题1:上述序列正确吗?

问题2:什么是node.js队列?它是否是使用epoll、kqueue或Windows上的IO完成端口的一部分?它是否是模块通知node.js线程某些IO已完成的回调机制?它如何工作?


1
Node.js 简单地使用 libuv,它是一个用于 C 的非阻塞 IO 库。如果你想知道 libuv 是否在线程池内部执行任何阻塞调用,请去阅读相关文档。 - Raynos
3
如果你有一个小时的空闲时间,为什么不让Node.js的创始人自己解释为什么以及如何构建它呢?非常有趣。只需在Google中搜索"ryan dahl"和"node.js"... Node.js的历史:http://www.youtube.com/watch?v=SAc0vQCC6UQ 你可以找到一些演示文稿,在其中他会详细介绍。 - nisc
2个回答

9

Node.js并不像你所猜测的那样完全管理这一切。它依赖于操作系统来处理大部分异步IO,根据操作系统使用select/epoll/kqueue。"他们"只是发出调用,操作系统会回复一个流、块等等。至于事件部分,这是内置在V8中的,它会将回调函数与特定事件绑定,就像在浏览器中一样。最后,你可以查看libuv,它是与Node一起编写的,并由Joyent维护。它在Github上是开源的,如果你真的想要了解详情,可以浏览代码=D


虽然不是专家,但这可能取决于您调用的模块。从8.1版本开始,子进程最终会调用process_wrap.cc#L226中的uv_spawn,其中有一些关于uv_spawn如何工作的解释在此处。还请参见internal/child_process.js#L292 - Ben Creasy
注意到libuv文档中提到:“与网络I/O不同,没有平台特定的文件I/O原语可供libuv依赖,因此当前的方法是在线程池中运行阻塞文件I/O操作”。 - Ben Creasy

-1

我高度怀疑Node.JS会走与Twisted相同的路线,只使用非阻塞IO和Greenlets。对于这种情况来说,操作系统线程似乎相当低效。


Greenlet是一种虚拟执行线程,它不使用操作系统级别的线程。Twisted和Gevent是使用它们的Python库之一。Greenlets通常依赖于协作式多任务处理和非阻塞IO以实现高速度和效率。基本上,它通常涉及包装阻塞IO函数以使用非阻塞IO,检查结果,并立即切换到另一个Greenlet,如果套接字或文件没有准备好。 - Campadrenalin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接