为什么我要用Node.js?

翻译自Why The Hell Would I Use Node.js? A Case-by-Case Introduction

#引言
JavaScript 正越来越流行并且伴随着一些变化。当下的web开发早已今非昔比,多年前不能想象的事情都变成了现实,比如将JavaScript用在服务器端或者将之像使用Flash和Java Applets一样封闭在沙盒(sandbox)内。

在深究Node.js之前,你可能有兴趣了解JavaScript全栈部署,通过使用统一的语言和数据格式(JSON),它允许你optimally重用开发资源。与其说这是Node.js的优点不如说是JavaScript的优点,在这里我们不做详细讨论,但是将Node加入你的stack将会给你巨大的优势。

正如维基百科所描述:“Node.js是对Google V8 JavaScript 引擎(libcv平台的抽象层)的一个编译打包,是Javascript的一个核心的库,并且其本身就是用Javascript写的。除了这些,Node.js的目标正如其发明者 Ryan Dahl所述:创建像Gmail一样的实时动态并且具有push capability的网站,在Node.js的世界里,他给予开发者以non-blocking,事件驱动I/O的工具。

After over 20 years of stateless-web based on the stateless request-response paradigm, we finally have web applications with real-time, two-way connections.

Node.js使建立在websockets技术上的实时应用大放异彩。20年来,web应用都是基于无状态的请求-响应模式的,请求只能由客户端发出,服务器响应;但是这一切都在现在结束了,实时的web允许服务器和客户端发出请求、响应请求,并且这一切都是基于现有的web stack。

可能会有人说,Flash和Java Applets在几年前就可以这么干了,但是,他们都是运行在虚拟沙盒环境中的,他们只是把web当成是把数据送到客户端的交换协议。并且,他们是独立运行的,大多数需要非标准端口(非熟知端口),这都需要额外的权限。

这是因为这些优势,Node.js在许多高利润企业中扮演重要的角色。

这篇文章不仅讲述Node.js的诸多优点是怎样完成的,还会用一些经典的web应用实例模块来阐述为什么你要用Node.js或者为什么你不用Node.js。

Node.js是怎么工作的

Node.js的主要思想是:使用非阻塞的,事件驱动的I / O来保持轻巧高效,从而服务于 跨分布式设备运行的数据密集型实时应用程序。
真是拗口。

What it really means is that Node.js is not a silver-bullet new platform that will dominate the web development world. Instead, it’s a platform that fills a particular need.

需要真正明白的是,Node.js从来就不是一个新的会主宰web开发的新平台,相反它是一个恰好填补了一个特定需求的平台。你需要明确的知道,你不能对计算密集型的程序用Node.js,实际上如果将Node.js用于计算密集型程序会完全掩盖它的优点。Node.js非常适合用来开发快速的,可扩展的网络应用程序,因为Node.js能处理大量并行的连接请求。

传统的web-serving技术在每个请求到达后,会生成一个新线程用来服务于这个请求,这些新线程会不断占用服务器内存,直到耗尽系统内存。Node.js则不一样,它以单线程的、非阻塞I/O工作,所以他可以支持数万的并发请求。

传统web和Node.js工作方式对比图

让我们简单计算一下:假设每个线程占用2MB的内存,那么一个拥有8GB内存的系统,加上线程切换最多只能同时处理4000个连接请求,当然这是使用传统web-serving技术情况下的计算。如果使用Node.js,那么这一数量将达到1M

所有的客户端请求全部由一个线程负责确实是一个问题,并且这是程序员在Node.js编程时候的一个陷阱。首先,密集的计算如果堵死Node.js的单线程,那么随后而来的需要该线程提供服务的连接,在当前的计算没有完成之前都得不到响应。其次,开发人员需要格外小心不能让异常触碰到Node.js的事件循环的核心,因为任何异常都将导致Node.js的终止。

普遍采用的防止异常的技术是将异常作为caller的回调参数,而不是简单的丢弃。即使有一些异常真的到达Node.js的事件循环核心,那么有很多可以监控Node线程的工具可以恢复崩溃的线程,最常用的是Forever module或者外部系统工具如upstat和monit

NPM: Node包管理工具

说到Node.js不得不提的是其内置的包管理工具,该工具在每个Node.js的版本上都默认安装。NPM模块的思想跟Ruby Gems的思想类似:通过网上仓库提供大量可复用的模块。

所有可用模块的完整名单可以在NPM的网站上找到,你也可以使用Node.js提供的NPM命令行工具。该模块是开放的,任何人都可以提交自己的模块到NPM的仓库中。一个简单的对NPM的介绍可以在这里找到。
一些常用的NPM模块有:

  • express - Express.js, 一个受Sinatra启发的web开发框架
  • connect - Connect 是一个可扩展的HTTP服务器框架,提供一批高性能的中间件;Express的基础架构 。
  • socket.io and sockjs - 两个最有名的websocket服务器端组件。
  • Jade - 最有名的模板引擎之一,Express.js的默认模板引擎。
  • mongo and mongojs - 提供API来访问MongoDB数据库。
  • redis - Redis 客户端库。
  • coffee-script - CoffeeScript 编译器,使开发人员可以使用Coffee编写Node.js代码。
  • underscore (lodash, lazy) - 最受欢迎的实用函数库,和它的两个变形(据说性能更好)。
  • forever - 可能是最流行的可以是你的Node.js代码免除任何异常的骚然,持续运行的模块。

一些应该使用Node.js的地方

聊天

从IRC(Internet Relay Chat)到今天所有一切可以被应用到Node.js上的,聊天是典型的多用户实时应用。

聊天应用是用来讲解Node.js最好的应用,因为它轻量级,数据密集并且运行在多种分布式设备上。同时它也是用来学习Node.js最好的例子,虽然简单但是它可以覆盖Node.js中典型的知识点。

下面我们试着了解一个聊天应用到底是怎么工作的。

最简单的例子,假设有三个人连接到我们聊天室,他们发送信息的方式是一到多,

在服务器端,我们有一个简单的Express.js程序包含以下两件事情:1)对于GET ‘/‘的请求,改程序返回一个包含信息板和可以输入信息的网页,2)一个websocket程序监听发自websocket客户端的新消息。

在客户端,我们有一个HTML网页,包含若干处理程序,其中之一是可以发送信息的发送按钮的程序,另一个是监听websocket客户端新消息的程序。
如果其中一个客户端发送了一条信息,那么将会:

  1. 浏览器捕获发送事件,并通过websocket客户端发送输入的信息。
  2. 服务器端的websocket收到来自该客户端的信息,然后广播该消息到所有连接到它的客户端。
  3. 所有的客户端都将通过websocket的客户端收到一条新消息,并且就地更新该信息到网页上的信息板上。
    websocket

这是最简单的一个例子。一种稳健的方案是基于缓存的或者更先进的方案,比如,用一个消息队列来路由其中的消息到客户端,用更稳健的消息分发机制,这些机制可以处理短暂的连接丢失或者在那些注册过的用户离线的时候存储暂时的信息。

API ON TOP OF AN OBJECT DB

Node.js 特别适合从 object 数据库取数据,JSON格式的数据免除了数据转换。

如果你正使用Rails,你首先需要把JSON格式的数据转换成二进制模式的, 然后通过HTTP传输到客户端,在客户端重新转换成JSON。换成Node.js, 你只需一个REST API就可以从数据库中取得数据,并且不用担心JSON格式和数据库中读取或者写入的数据。所以,总的来说,使用Node.js你可以免除数次数据的中间转换,因为从客户端到服务器端再到数据库全部都是一种格式。

QUEUED INPUTS

如果同时收到大量并发数据,数据库会成为系统的瓶颈。如前所述,Node.js能够很轻松的应对大量的并发请求,但是对数据库的操作时阻塞操作,所以一种解决方法是在数据真正写入数据库之前确认客户端的行为。这种方法能够保持服务器即使相应,特别是在客户端不是那么迫切需要知道数据已经成功写入数据库的情况下。比如成批处理的日志或者用户追踪数据,它们是不需要即时的反应到数据库上的(更新Facebook的“like”按钮),只要最终一致就行。

使用某种缓存或者消息队列,将数据发送到另一方单独处理数据的程序或者后台某个计算密集型服务等具有比Node.js具有更好计算性能的平台。这种平台可以是其他运行在其他硬件上的高性能高吞吐的语言或者框架。

images

简而言之:Node.js可以将发往数据库的请求暂时存在一旁以后处理,通过这种方式表现的好像已经成功处理了一样。

DATA STREAMING

In more traditional web platforms, HTTP requests and responses are treated like isolated event; in fact, they’re actually streams. This observation can be utilized in Node.js to build some cool features. For example, it’s possible to process files while they’re still being uploaded, as the data comes in through a stream and we can process it in an online fashion. This could be done for real-time audio or video encoding, and proxying between different data sources (see next section).

#related
Node入门 >> 一本全面的Node.js教程