Node.js 回调机制 - 哪个线程处理回调?

11

我刚接触nodeJS,对node的单实例模型感到好奇。在一个简单的nodeJs应用程序中,当一些阻塞操作使用回调函数异步处理时,主线程是否也会处理回调函数呢? 如果请求是从数据库获取数据,并且有100个并发用户,每个数据库操作需要几秒钟,当最终触发回调函数时(对于每个连接),主线程是否也用于执行回调函数? 如果是这样,nodeJs如何扩展并如何快速响应?


发现这个链接非常有用:http://rickgaribay.net/archive/2012/01/28/node-is-not-single-threaded.aspx - Some guy
1个回答

10

每个Node.js实例都在单个线程中运行,没有例外。当您进行异步调用(例如网络请求)时,它不会在您的代码或任何其他地方等待响应。它有一个事件循环负责这些操作。当响应准备好时,它将调用您的回调函数。

这种方式能够得到非常高效的性能,因为它不需要大量线程和所有内存开销,但这意味着您需要小心不要做同步阻塞的操作。

关于事件循环的解释可以在http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/找到,Ryan Dahl在 jsconf 上的演示也值得观看,链接为http://www.youtube.com/watch?v=ztspvPYybIY。您见过工程师因技术演示而获得起立鼓掌吗?


1
这对我来说还有点不清楚。如果有100个并发用户,那么会运行一个节点实例还是100个?考虑到有一个带回调的异步调用,并且线程(比如线程A)在放置网络/数据库请求后退出了该代码片段,当回调被触发时,是线程A执行此回调吗? - Some guy
3
如果有100个“并发用户”(即向nodejs实例发出网络请求的用户),那么仍然只有一个node实例。当请求被发送时,单个线程会处理它。当它进行异步调用以读取文件或访问网络服务等时,仍然是同一个线程。当访问完成并调用回调时,仍然是同一个线程。如果你可以使用某种负载均衡器来管理它们,你可以运行多个node实例,而node-cluster虽已计划,但仍处于试验阶段。 - deitch
2
@deitch 当只有一个线程同时执行100个任务时,如何避免阻塞?假设这100个任务中的每一个都需要1秒钟才能完成,如果它们全部在一个线程中执行,那么它们必须按顺序完成,这是否意味着它将会阻塞100秒? - user1663023
1
问题是,对于每个用户的1秒钟,它是1秒钟的CPU密集型处理,还是10毫秒的处理和另外990毫秒的等待网络、磁盘等?在大多数Web情况下,它是后者,这就是nodejs(和nginx)最适合的地方。如果是前者,那么你将需要很多node进程,或者转移到像Java/Scala这样的东西(无论如何仍然会使用相同数量的CPU,只是有更多的线程...) - deitch
1
当一个线程请求 I/O 操作时,它会被操作系统处理。你的线程不需要等待响应,所以它只需继续执行并等待事件循环通知 I/O 请求完成。 - Luis Carlos Chavarría

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