理解NodeJS和非阻塞IO

20

最近,我被注入了Node病毒,它正在程序世界中快速传播。

我被它的“非阻塞IO”方法所吸引,确实尝试了一些程序。

然而,目前我还无法理解某些概念。

我需要用通俗易懂的术语来回答我的问题(我来自Java背景)。

1. 多线程和非阻塞IO。

让我们考虑一个实际情况。比如说,我们有一个网站,用户可以注册。以下是代码。

..
..
   // Read HTTP Parameters
   // Do some Database work
   // Do some file work
   // Return a confirmation message
..
..

在传统的编程语言中,上述过程按顺序进行。如果有多个注册请求,Web服务器会创建一个新线程,然后就成为历史了。当然,程序员可以创建自己的线程来同时处理第2行和第3行。

在Node中,我理解的是,第2行和第3行将并行运行,而程序的其余部分则被执行,解释器每隔“x”毫秒轮询第2行和第3行。

现在我的问题是,如果Node是单线程语言,那么第2行和第3行的工作是什么,而程序的其余部分正在被执行?

2. 可扩展性

我最近读到LinkedIn已经将Node用作其移动应用的后端,并取得了巨大的改进。

有人能解释一下它如何产生如此大的影响吗?

3. 在其他编程语言中的应用

如果有人声称Node在性能方面有很大的优势,那么为什么其他编程语言没有采用这种非阻塞IO的范例呢?

我相信我肯定漏掉了一些东西。只有您能够解释并提供一些链接,这将非常有帮助。

谢谢。


4
我强烈建议您观看Ryah Dahl的原始演示(http://www.youtube.com/watch?v=ztspvPYybIY),它可以回答您所有的问题。 - Pradeep Simha
谢谢Pradeep。这帮了很多。 - Vishwas Shashidhar
3个回答

13
一个类似的问题已经被问过了,可能包含你所需的所有信息:如何在Node.js中使用单线程非阻塞I/O模型
但是我会简要介绍一下你的三部分: 1. 简单来说,第2行和第3行可以是这样的形式:
      db.query(..., function(query_data) { ... });
      fs.readFile('/path/to/file', function(file_data) { ... });

现在function(query_data)和function(file_data)是回调函数。db.query和fs.readFile函数将发送实际的I/O请求,但回调函数允许从数据库或文件处理数据的延迟直到收到响应。它并不真正“轮询第2行和第3行”。回调函数被添加到事件循环中,并与其各自的I/O事件的一些文件描述符相关联。然后它轮询文件描述符以查看它们是否准备好执行I/O操作。如果是,则使用I/O数据执行回调函数。
我认为短语“除了您的代码外,所有内容都是并行运行的”很好地概括了它。例如,“读取HTTP参数”之类的东西将按顺序执行,但像第2行和第3行中的I/O函数与添加到事件循环中的回调相关联,稍后执行。因此,基本上整个重点是不必等待I/O2. 由于1中所解释的原因,Node对于I/O密集型请求具有良好的扩展性,并允许同时连接多个用户。它是单线程的,因此不一定适用于CPU密集型任务的扩展。 3. 这种模式已经被JavaScript使用,因为JavaScript具有支持回调、事件循环和闭包的功能,使得这种操作变得容易。在其他语言中,情况并非总是如此。
这可能有点偏离主题,但这就是发生的要点。

谢谢,我已经看了不少视频,现在开始懂了。 - Vishwas Shashidhar
1
就像@Nathaniel所说,非阻塞IO范式需要支持回调,任何具有闭包的语言都可以实现这个模型.. ReactPHP是一个例子http://reactphp.org - Issam Zoli
1
@IssamZoli - 谢谢。我不知道为什么之前没有注意到reactphp。你提供的单个链接带我进入了react和rachet的旅程,以便与我的Laravel应用程序一起使用。非常感谢! - techfoobar

3

问题1:在程序的其余部分被执行时,第2和第3行代码的作用是什么? 答案:“没有”。第2行和第3行各自启动它们的各自的工作,但是这些工作不能立即完成,因为(例如)所需的磁盘扇区尚未加载 - 因此操作系统发出调用以获取这些扇区,然后“无事发生”(节点继续下一个任务),直到磁盘子系统(稍后)发出中断报告准备就绪,此时节点返回控制权到第2行和第3行。

问题2:单线程非阻塞几乎不会为每个传入连接提供任何资源(只是有关已连接套接字的一些清理数据)。这非常节省内存。传统的Web服务器“分叉”了一个全新的进程来处理每个新连接 - 这意味着需要制作所有位代码和数据变量的巨大副本,并且要对CPU进行时间切片以处理所有这些内容。这是非常浪费资源的。因此 - 如果您的负载是大量等待某些东西的空闲连接,正如他们的那样,node就更有意义。

问题3:几乎每种编程语言都已经拥有非阻塞I / O,如果您想使用它。Node不是编程语言,它是一个运行JavaScript并使用非阻塞I / O的Web服务器(例如:我个人10年前就在perl中编写了自己的完全相同的东西,谷歌也是如此(用C)开始时,我相信还有很多其他人也有类似的Web服务器)。非阻塞I / O并不是难点 - 让程序员理解如何使用它才是棘手的部分。Javascript对此效果良好,因为这些程序员已经熟悉事件编程。


1
尽管node.js已经存在了几年,但其性能模型仍然有点神秘。我最近开始写博客,并决定把node.js模型作为第一个主题,因为我想更好地理解它,分享我所学对其他人也有帮助。以下是我撰写的一些文章,解释了高层概念和一些权衡取舍: 阻塞与非阻塞I/O - 到底发生了什么? 了解node.js性能

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