为何要使用Node.js?

介绍

JavaScript的流行给它自己带来许多变化,Web开发的面貌也发生了巨大的改变。如今JavaScript不只能够运行在浏览器上,甚至能够运行在服务器上,像Flash或者Java Applets那样被包装在沙盒环境中运行,这在几年前这是很难想象的。前端

在深刻Node.js以前,你也许想知道使用JavaScript跨技术栈开发的优点,能够统一开发语言和数据格式(JSON),使开发者优化开发资源的使用。这些优点在Node.js和JavaScript的技术栈中更加明确,关于这些咱们不讨论太多,这是你将Node.js加入到技术栈后最明显的优点。java

维基百科中描述:“Node.js是Google V8引擎,libuv做为平台抽象层,JavaScript编写的核心库封装编译的。”不只如此,值得注意的是Node.js的做者Ryan Dahl目的是构建一个有实时推送能力的网站。灵感来自相似Gmail的应用。在Node.js中,他提供给开发者事件驱动、非阻塞I/O的模型。node

有人说:Node.js在使用WebSocket的推送技术建立的实时Web应用中大放异彩。为何它引发巨大的改变?在通过长达20多年基于无状态请求响应模型中,咱们最终有了实时、全双工通讯的Web应用,浏览器和服务器均可以初始化创建链接,自由的交换数据。这和传统的基于客户端初始化链接的Web响应模式有明显的对比。nginx

有人也许会说,咱们已经以Flash和Java Applets的形式使用过不少年了。但实际上它们只是运行在沙盒环境里,经过Web传输协议发送到客户端,它们孤立地运行在非标准端口上,可能会引入好比权限问题。web

由于这些优势,如今Node.js在那依赖本身独特利益的大公司的技术栈里扮演着关键性的角色。Node.js基金会整理了全部最佳实践,关于企业为何应该考虑使用Node.js。你能够在一篇短文中找到。算法

这篇文章中,我不只讨论那些已经实现的优势,还会结合一些经典的Web应用模型,告诉你为何你要使用Node.js,以及为何不要使用Node.js。数据库

它是怎样工做的?

Node.js最主要的特色:使用非阻塞、事件驱动I/O模型使其轻量、高效,可以构建数据密集型、实时的跨平台应用。这说明Node.js并非一颗主宰整个Web开发世界的银弹。相反,它是一个解决特殊需求的平台。明白这些是必要的,不要使用Node.js处理CPU密集型业务,若是你真的这么作了,咱们先前说过关于Node.js的优势都将不复存在。Node.js真正适合的是构建快速的、可扩展的网络应用,他的吞吐率可以胜任巨量的并发链接。express

和传统的Web服务技术相比,每一个请求到来建立一个新的线程,系统为每一个线程分配内存,最终由于内存不够而透支,Node.js工做在单线程,使用非阻塞I/O调用,可以承受上万的并发链接。咱们很快得出一个结论:假设每建立一个线程系统为它分配2M内存,在一台8G内存的系统上它的最大并发数是4000(这个结论来自Michael Abernethy的文章《Just what is Node.js?》,于2011年出版在IBM developerWorks,不幸的是如今不能阅读了),加上线程上下文切换的花费,这是使用传统Web服务技术的场景,Node.js实现的可扩展性远远超过它。redux

固然全部客户端请求都使用同一个线程是有问题的,它是Node.js应用的一个潜在陷阱。首先,大量的计算会阻塞单线程直到计算完成。第二,开发者必定要注意不要让异常冒泡到应用顶部,这可能使整个Node.js程序崩溃。后端

避免异常冒泡到程序顶部,能够将错误当作回调函数的参数。即便有些未捕获的异常,开发工具可以监视Node.js进程,而且完成必要的崩溃实例恢复(当前用户的session是没有办法恢复的),最常使用的工具就是forever,或者外部系统工具,也能够直接重启。

NPM: Node包管理工具

当咱们讨论Node.js时,须要了解一下NPM,它是内置用来管理Node.js包的工具,安装Node.js时就会默认安装它。NPM的思想和Ruby的Gem十分类似:一个可公开的、可重用的组件库,可经过在线仓库轻松安装,可以进行版本和依赖项管理。

下面是一些NPM包,你能够在NPM官网找到它们,或者使用NPM命令行工具下载到你的Node.js项目里。NPM是一个开发的生态系统,任何人能够发布本身的NPM模块,并在NPM官网上找到它。你能够在Beginner’s Guide上找到一份简介,还有一份开发NPM包的指南开发NPM包的指南.

这是常常用到的一些NPM包:

  • express - Express.js是一个受Sinatra启发的Node.js的Web开发框架,它是今天大部分Node.js应用程序的事实上的标准。

  • koa - 和Express是同一个做者,基于中间件机制的Web框架,比Express更加轻量。

  • socket.io - Node.js服务端实时应用的框架。

  • request - 一个HTTP客户端请求工具。

  • async - async是一个用来处理JavaScript异步操做的工具库。

  • bluebird - bluebird实现了Promise/A+规范,是一款性能很是好的Promise工具库.

  • lodash and underscore and Ramda -是JavaSciprt的扩展库,提供了丰富的方法。

  • debug - 开发过程当中用到的调试工具。

  • forever and nodemon - 经常使用的进程守护工具,上文提到过,能够在开发模式下保护你的进程。

能够用Node.js实现的应用

聊天室

聊天是典型的实时、多用户应用。在当时IRC经过许多专有和开放的协议运行在不标准的端口上,如今在Node.js环境下,咱们能够在标准的80端口上,实现这些聊天应用。

能够说聊天应用是体验Node.js优势最好的例子,聊天应用轻量化、高流量,数据密集型(计算和处理时间短,最简单作一次转发)、跨终端、也是学习Node.js绝佳的例子,它包含了大多数在一个典型的Node.js应用中用到的模式。

分析一下聊天室是如何工做的。

最简单的例子,在咱们的站点上只有一个聊天房间,所用的用户采用一对多的形式交换消息。假设咱们的房间里有三个已经创建链接的用户。

在服务端,咱们有一个简单的Express.js的应用,它实现两个功能:1.当咱们请求根目录时,它返回一个包含消息面板,用来发送消息的按钮,还有输入框的网页。2.一个websocket服务,监听新消息并发送给客户端。

在客户端,咱们有一个监听两个事件的页面,其中一个监听发送按钮点击事件,获取输入框中的消息,并经过websocket发送到服务端,另外一个事件监听websocket客户端新消息(这个消息来源于其余用户,服务端转发给全部在这个聊天房间的用户,而且客户端显示消息)。

当一个用户发送消息,会通过以下几步:

  1. 浏览器监听发送按钮点击,JavaScript处理事件,从输入框中获取消息内容,websocket发送消息。

  2. 服务端webSocket链接收到消息,经过使用broadcast方法,进一步将它转发给其余创建链接的用户。

  3. 全部用户经过客户端websocket收到了来自服务端的推送消息,客户端将获得的消息,追加到页面消息面板的适当位置。

这是最简单的例子了,若是你想让它更加健壮,你可使用如Redis这样的高速缓存,或者更高级一点,用消息队列处理客户端的消息分发,而且创建更强大的链接机制,用来减小创建临时链接的损失,还能够为已经注册的用户保存离线消息。无论你是否能实现这些功能,Node.js的最基本的功能还是处理事件和并发链接,而且保证用户体验的流畅性。

非关系型数据库数据接口

Node.js不只在实时应用上作的很出色,它和很是适合从非关系型数据库读取数据。Node.js使用JSON存储数据,能够无阻抗失配,不须要数据转换。

举个例子,若是你使用用Rails开发,你会将JSON数据转换为二进制数据,而后经过Http协议发送到浏览器,数据须要转换为JSON格式才能被Backbone.js,Angular.js等框架或者普通Ajax调用。若是你使用Node.js开发,你能够经过REST API返回JSON对象给浏览器使用。此外,你也不须要担忧在读写数据库(MongoDB)时会发生数据转换错误。总之,你能够没必要在客户端、服务器、数据库使用统一序列化格式。

队列

若是你的应用有高并发的数据,数据库会成为应用的瓶颈。上文提到,Node.js能够轻松地处理高并发链接,可是数据库访问倒是阻塞的操做,在这种状况下,咱们就有麻烦了。解决方案就是,咱们先接受客户端的请求,并返回结果,而后才真正的写到数据库中。

使用这种方法,系统能在高负载的状况下保证响应能力,尤为是在客户端不须要确认是否存数据存储成功的状况下。最典型的例子就是:日志或者记录用户行为的数据,批次处理而且不会马上使用的状况;操做不须要马上作出反应(就像Facebook更新点赞数据),在使用NoSQL的状况下是可行的。

数据经过某种缓存或者消息队列(如:RabbitMQ,ZeroMQ)进行排队,等待被数据库写线程批量写入,或者计算密集型的后端服务进行处理。类似的行为能够经过其余语言或者框架来实现,可是在相同的硬件下,Node.js能保持更高的吞吐量。

数据流

在传统的Web平台,HTTP请求和响应被当作孤立的事件来对待;实际上他们都是数据流。这个事实被Node.js利用构建一些很酷的特性,例如:咱们能够在文件上传过程当中就进行处理,因为数据是以流的形式传输过来,咱们能够在线处理它。能够用来作实时语音或视频的编码,在不一样的数据源之间作代理。

代理

Node.js和容易搭建一个服务端代理,它能够以非阻塞的方式处理大量并发链接。尤为是用在为不一样响应时间的服务作代理,或者从多个源点收集数据。

举个例子:服务端应用须要和第三方资源沟通,从多个源点拉取数据,或者将图像视频等资源存储到第三方服务。

尽管专用代理服务确实存在,你能够在代理基础设施不全或者须要本地开发的解决方案时用Node.js来实现。在开发时你可使用Node.js服务搭建静态资源客户端应用,代理API请求。在生产环境下你可使用专用代理服务,如:nginx、HAProxy等。

中间层

让咱们回到应用水平。中间人交易软件在桌面软件占主导地位,但很容易用实时网络解决方案代替,它用来跟踪股票价格,进行计算/技术分析,并建立图表。若是是基于Web的实时应用的解决方案,经纪人轻松地切换工做站或工做场所。

应用监控

另外一种常见的场景,在Node.js中使用WebSocket技术跟踪网站访问者并实时可视化他们的交互。你能够从你的用户那里收集实时的统计数据,甚至能够经过在你的漏斗中到达一个特定的点,打开一个通讯通道来与访问者进行有针对性的交互,从而将其移动到下一个层次。(若是你感兴趣,能够去了解CANDDi,它已经把这个想法产品化了)。

系统监控

如今咱们聊一条基础设施方面的问题。设想一下,有一个Sass平台想要提供给用户一个服务监控页面,例如GitHub’s status page。使用Node.js的事件循环机制,咱们能够构建一个强大的信息板,来监控服务器的状态,以异步的方式将数据经过WebSocket发送到客户端。

无论是内部仍是公众服务,均可以经过这种技术实时报告状态。咱们进一步推进这个想法,而后想象一个工做在电信运营商的Network Operations Center (NOC)监控应用,云/网络/主机提供商,或者是一些金融机构,都运行在Node.js和WebSockets技术栈上,而不是java或java小应用程序。

注意:不要试图使用Node.js构建硬实时系统,即那些要求一致响应时间的系统。Erlang构建这类应用或许是更好的选择

Node.js适合用在哪?

web应用程序

使用Express.js框架能够在服务器上构建一个传统的Web应用,有一种说法,Node.js的请求响应模型用来渲染HTML页面不是最好的用处。这个观点是有争议的,他们的考虑以下:

同意的观点:

  • 若是你的应用没有CPU密集的处理,你可使用Node.js构建自上而下的应用,或者作最底层对象关系数据库(MongoDB)的读写,这大大简化了开发。

  • 爬虫抓取到一个完成的HTML响应,要比获得一个单页面或者使用WebSocket的应用,对SEO更加友好。

反对的观点:

  • 任何CPU密集型的业务将会阻塞Node.js的响应,若是没有这种业务单线程表现很好,相反的,你能够增长CPU的运算量试试。

  • 使用Node.js时,任何关系型数据库都是至关痛苦的(详情见下文),若是你肯定要用关系型数据库,帮本身一个忙,你能够试试Rails,Django,或者ASP.Net。

有一个替代CPU密集型业务的解决方案,建立一个告诉可伸缩的消息队列后台程序,Node.js像前台接待员同样异步地接受客户端请求。

Node.js不适合用在哪?

使用关系型数据库的Web应用程序

Node.js的Express.js和Ruby on Rails进行比较,后端访问关系数据库干净的决策比较受到支持。

Node.js关系数据库工具发展仍在早期阶段;它们工做的至关不成熟也不友好。另外一方面,Rails自动提供数据访问设置权开箱与DB模式迁移的支持工具和其余Gems。Rails及其对等框架具备成熟的、已证明的活动记录或数据映射器数据访问层实现,若是你试图以纯JavaScript复制它们,你会很是怀念这段经历。

你若你还想继续走Node.js这条路,准备好掉几根头发吧。记得关注一下Sequelize 和 Node ORM2二者都还不成熟,但最终可能会迎头遇上。

将Node.js单独用做前端是可能的,并且并很多见,同时保持Rails后端和对关系数据库的简单访问。

沉重的服务端计算

当涉及到大量的计算,Node.js是否是最好的平台。你确定不想使用Node.js建一个斐波纳契计算服务器,总之,任何CPU密集型操做都会使Node.js事件驱动,非阻塞I/O的的模型变得毫无做用,由于请求会被阻塞,由于线程被你的数字梳理给占据了。

如上所述,Node.js使用单线程而且只使用单核CPU,若是你打算在多核CPU上部署服务,Node.js核心团队开发了集群模块。你也能够创建多个Node.js引用实例,让后经过Nginx代理到它们。

在使用集群是,你仍是应该将计算量重的操做放到像RabbitMQ这样的消息队列里,在合适的时候拿出来处理。

尽管最初的后台处理可能在同一台服务器上运行,但这种方法具备很是高的可伸缩性。这些后台处理服务能够很容易地分发到分离的worker服务器,而无需配置前向Web服务器的负载。

固然,你能够在其余平台上使用同样的作法,但Node.js有高的请求/秒的吞吐量,咱们已经谈过,由于每一个请求是一个小的任务处理的很是快速和有效的。

总结

咱们从理论到实践讨论Node.js,从它的目标和抱负开始,到它的甜头和陷阱。当开发者遇到Node.js的问题时,认为阻塞是万恶之源,99%的缘由是滥用Node.js形成的。

记住,Node.js不是为了解决计算扩展问题而产生的,而是为了解决I/O扩展问题,在这方面它作的很出色。

为何使用Node.js?若是您使用的状况不包含CPU密集型操做或访问任何阻塞的资源,你能够利用Node.js的好处,构建快速和可扩展的网络应用。欢迎来到实时Web应用。


往日精选:

前端如何优雅切图

仅使用CSS,带你建立一个漂亮的动画加载页面

使用 React 实现页面过渡动画仅需4个步骤

像数据库同样设计你的 redux 数据结构

为何我认为数据结构与算法对前端开发很重要?

深刻贯彻闭包思想,全面理解JS闭包造成过程

提升 | 10个JavaScript难点

JavaScript数据结构系列终篇——全系列索引

如何写好技术简历 —— 实例、模板及工具

29个前端工程师和设计师必备的Chrome插件

2017年前端开发技术栈

掌握Chrome开发工具:新一代前端开发技术

5个你可能不知道的CSS属性

测量 web 性能,很是简单


既然读到这里了,那就推荐一个有意思的公众号:

充实的脑洞

天天深夜给你看一些有趣的东西

长按二维码关注




小手一抖,资料全有。长按二维码关注京程一灯,阅读更多技术文章和业界动态。


本文分享自微信公众号 - 前端先锋(jingchengyideng)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索