前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么要使用Node.js?

为什么要使用Node.js?

作者头像
疯狂的技术宅
发布2019-03-28 11:13:38
3.1K0
发布2019-03-28 11:13:38
举报
文章被收录于专栏:京程一灯京程一灯

介绍

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

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

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

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

有人也许会说,我们已经以Flash和Java Applets的形式使用过很多年了。但实际上它们只是运行在沙盒环境里,通过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真正适合的是构建快速的、可扩展的网络应用,他的吞吐率能够胜任巨量的并发连接。

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

当然所有客户端请求都使用同一个线程是有问题的,它是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应用。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-08-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 京程一灯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 它是怎样工作的?
  • NPM: Node包管理工具
  • 可以用Node.js实现的应用
    • 聊天室
      • 非关系型数据库数据接口
        • 队列
          • 数据流
            • 代理
              • 中间层
                • 应用监控
                  • 系统监控
                  • Node.js适合用在哪?
                    • web应用程序
                    • Node.js不适合用在哪?
                      • 使用关系型数据库的Web应用程序
                        • 沉重的服务端计算
                        • 总结
                        相关产品与服务
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档