当前位置: 首页 > 科技观察

我为什么要使用Node.js?逐个案例

时间:2023-03-16 20:51:37 科技观察

介绍JavaScript的流行带来了如此多的变化,以至于今天使用它的Web开发看起来非常不同。就像在浏览器中一样,我们现在可以在服务器上运行JavaScript,从前端到后端,如此巨大的反差是难以想象的,因为仅仅在几年前,Javascript还是像Flash或Javaapplets这样嵌入到网页中运行的沙盒环境。在深入研究Node.js之前,您可能想阅读并了解使用跨堆栈JavaScript(跨堆栈的JavaScript)的好处,它统一了编程语言和数据格式(JSON),让您最大限度地重用开发人员资源。由于这更像是JavaScript的特性,我不会在这里过多讨论。但这确实是人们在开发周期中使用Node的一个关键好处。正如维基百科所说:“Node.js是Google的V8引擎、libuv平台抽象层和用Javscript编写的核心库的包装器。”此外,值得注意的是,Node.js作者RyanDahl的目标是创建一个具有实时推送功能的站点。在Node.js中,他为开发者提供了一个使用事件驱动进行异步开发的优秀解决方案。(注:V8由谷歌开发,是目前公认最快的Javascript解析引擎,libuv是一个开源的、为Node定制的跨平台异步IO库。)简而言之:Node.js在实时Web应用中使用基于WebSocket的推送技术。这意味着多大的革命性?好吧,经过20多年基于无状态请求-返回机制的无状态交互,我们终于有了实时的、双向连接的Web应用程序,客户端和服务器都可以在其中自由发起通信和交换数据。与此形成鲜明对比的是传统的Web响应模式,总是客户端主动发起通信,服务端被动返回。此外,这些基于在标准端口80上运行的开放Web组件(HTML、CSS和JS)。有人可能会争辩说我们多年来一直在使用Flash和JavaApplets——但实际上,这些只是使用网络的沙盒环境向客户端传递数据。它们都是独立运行的,并且经常在需要额外权限等的非标准端口上运行。Node.js凭借其独特的优势,如今已经在众多知名公司的产品中扮演了关键角色。在这篇文章中,我们不仅会讨论这些优势是如何实现的,还会讨论为什么您应该使用Node.js作为一些经典Web应用程序模型的替代品。Node.js是如何工作的?Node.js的主要思想是使用非阻塞、事件驱动的I/O操作来保持跨平台(跨分布式设备)数据密集型实时应用程序的轻量级和高效处理。这听起来有点开玩笑。它真正的意思是Node.js不是一个即将主宰Web开发世界的灵丹妙药平台。相反,它是一个满足临时需求的平台。您绝对不想使用Node.js进行CPU密集型操作。事实上,用它来进行繁重的计算,就等于丢掉了Node几乎所有的优势。Node真正的亮点在于构建高性能、高可扩展性的互联网应用——因为它可以处理巨大的、高吞吐量的并发连接。它的工作原理非常有趣。传统的网络服务技术是每增加一个新的连接(请求)就产生一个新的线程。这个新线程会占用系统内存,并最终占用所有可用内存。Node.js仅在单线程中运行,使用非阻塞异步I/O调用,所有连接都由该线程处理。加上libuv的加分项,可以让它支持数以万计的并发连接(都挂在线程的事件循环中)。做个简单的计算:假设是一个普通的web程序,一个新的连接会占用2M的内存。当运行在8GBRAM的系统上时,包括线程间上下文切换的开销,并发连接的最大开销理论值为4000。这是传统Web服务器技术下的处理情况。而Node.js已经达到了约1M并发连接的扩展水平(相关证明)。当然,当所有客户端请求共享一个线程时就会出现问题,这也是编写Node.js应用程序的潜在缺陷。首先,大量的计算可能会导致Node的单线程暂时失去响应,导致其他所有客户端请求都被阻塞,直到计算完成才恢复正常。其次,开发人员需要非常小心,不要让Exception阻塞核心事件循环,因为这将导致Node.js实例终止(有效地使程序崩溃)。(作者注:如果PHP中的一个页面挂了,不会影响网站的运行,但是Nodejs是一个线程一个线程处理所有链接的,所以无论是计算卡还是异常阻塞,它可能会影响网站。所有其他链接。解决方案稍后讨论。)避免在抛出异常时中断进程的方法是使用回调传递异常(而不是像在其他环境中那样抛出它们)。即使一些未处理的异常阻塞了程序,仍然有各种解决方案,并且有很多策略和工具可以用来监视Node进程以执行必要的崩溃后恢复工作(虽然你将无法恢复user'ssession),最常见的是使用Forever模块,或者使用upstart、monit等其他外部系统工具。NPM:Node包管理器当我们讨论Node.js时,一个不容忽视的地方是默认内置的模块管理工具——NPM。它的灵感来自RubyGems(具有版本和依赖管理的管理工具,以及通过在线存储库轻松安装可重用组件)。可以在NPM的网站(https://npmjs.org/)上找到完整的公共模块列表,或者使用随Node.js安装的NPMCLI工具。模块生态对所有人开放,任何人都可以发布自己的模块,所有模块都可以在NPM仓库中找到。您可以在http://howtonode.org/introduction-to-npm找到NPM的简要介绍(有点旧,但仍然可读)。目前非常流行的一些NPM模块有:express–Express.js,是一个简单灵活的node.jsweb应用程序框架,它已经是大多数Node.js应用程序的标准框架。你已经可以在很多Node.js书中看到它了。connect–Connect是一个Node.jsHTTP服务扩展框架,提供高性能的“插件”集合,称为中间件,是Express的基础部分之一。socket.io和sockjs-服务器端两个最流行的websocket组件。Jade-流行的模板引擎之一,是Express.js的默认模板引擎。它的灵感来自HAML。mongo和mongojs——封装了MongoDB的各种API,不过我平时工作也推荐使用mongoose。redis-Redis的客户端库。coffee-script-CoffeeScript编译器,允许开发人员使用Coffee编写他们的Node.js程序。underscore(lodash,lazy)-一个优秀的JavaScript实用程序库,一个Node.js的包装器,以及两个采用略有不同实现以获得更好性能的对应物。forever-可能是确保节点脚本持续运行的最佳工具。还有很多其他不错的模块,这里就不一一列举了(希望大家不要冒犯没有列举的)。Node.js应该用在什么地方?ChatChat是最典型的多用户实时交互应用。从IRC开始,许多开源或非开源协议都运行在非标准端口上,但现在,使用Node.js可以解决这些问题——在标准端口80上运行WebSockets。聊天应用程序是Node.js的最好例子可以做到:轻量级、高流量、数据密集型(尽管计算能力低),能够在跨平台设备上很好地处理数据密集型操作。此外,聊天是一个非常值得学习的用例,因为它很简单并且涵盖了典型Node.js目前使用的大多数解决方案。让我们试着想象一下它是如何工作的。在最简单的情况下,我们的网站上有一个聊天室,用户可以在其中发送消息,当然是以一对多的方式。例如,假设共有三个人连接到我们的站点。在服务器端,我们有一个使用Express.js构建的简单站点。这个网站实现了两件事:1)当处理一个路径为'/'的GET请求时,它会发送一个留言板和一个'带有'发送'按钮的页面2)一个监听客户端发送的新消息的websockets服务.在客户端,我们有一个HTML页面,上面有两个js方法,一个是用来触发事件的“发送”按钮,会通过websocket发送输入消息,另一个方法是在客户端使用websocket监听来自服务器的推送(例如,其他用户发送的消息)。当客户端发送消息时,发生的事情是:在浏览器上,点击发送按钮触发js函数,将输入框中的文本通过websocket消息发送给服务端的websocket客户端(页面初始化时连接,加载)的)。服务器端的websocket组件接收到消息,然后通过广播的方式转发给所有其他连接的客户端。通过页面运行的websocket客户端组件,所有的客户端都可以收到这条新的推送消息。然后js处理函数就可以把这个消息添加到文本框里了。这是最简单的例子。为了更好的解决方案,您可以使用Redis数据库进行简单缓存。在更高级的解决方案中,您可能需要一个消息路由器来专门处理消息队列,以及更健壮的发送机制,例如在为离线注册用户发送或存储未收到的消息时覆盖暂时离线的用户。新闻等等。但无论您进行何种改进,Node.js都将遵循一个基本原则:响应事件、处理多个并发连接并保持流畅的用户体验。对象数据库接口(APIONTOPOFANOBJECTDB)虽然,Node.js确实擅长实时交互应用,也非常适合通过对象数据库(objectDB)(如MongoDB)查询数据。以JSON格式存储的数据可以让Node.js直接处理,无需担心数据转换和匹配。例如,如果您使用Rails,您会将JSON数据转换为二进制模型,然后在Backbone.js、Angular.js或jQueryAJAX调用数据时将其转换回JSON。如果是Nodejs,你可以简单地通过RESTAPI导出JSON对象供客户端使用。另外,如果你在读写数据库时使用MongoDB,你就不用担心JSON和任何数据之间的格式问题。简而言之,您可以避免多次数据转换问题,无论是在客户端、服务器还是数据库上。队列输入如果您正在接收大量并发数据,您的数据库可能会成为您的处理瓶颈。如上所述,Node.js可以轻松处理并发连接。然而,由于数据库操作是一个阻塞操作(在本例中),这就是它变得棘手的地方。Node.js的解决方案是在数据真正写入之前承认客户端的数据是真实的。这样,系统在高负载的时候也能继续保持响应能力,这在客户端不需要严格保证一条数据写入成功的时候特别有用。典型的例子包括:日志记录或用户跟踪数据(user-trackingdata)记录,这些记录将被批量处理并在以后使用;还包括最终一致性(因此,在NoSQL中经常使用)是可以接受的,而不是需要立即响应的Actions(例如更新Facebook上的点赞数)。数据通过缓存或消息队列的一些基础组件(如RabbitMQ、ZeroMQ)进入队列,通过独立的数据库批量写入进程,或者通过更高性能的计算密集型后端服务,将数据逐一消化。处理。其他语言/框架也可以实现类似的操作,但是在同样的配置下,无法实现nodejs的高吞吐和高并发。简单地说:使用Node,您可以将数据库操作搁置一旁,并在以后处理它们,假设它们成功了。(作者注:在开发中,通常是通过回调函数异步处理一个耗时的操作,主线程继续执行)数据流在更传统的网络平台上,HTTP请求和响应更像是孤立事件;然而,实际上,它们都是数据流。这个观察可以用来在Nodejs上构建一些很酷的特性。因为数据通常以流的形式接收,我们可以在网站上在线处理上传的文件。这样就可以实现实时的音视频编码,以及不同数据源之间的编码(代理见下一段)。(作者注:Node可以代替apache等webserver处理数据,所以开发者可以直接一个接一个的接收客户端上传的数据,实时处理。上面这段话听起来有点抽象,但是大家可以简单想象一下无需打开YY或QQ即可打开网页执行语音和视频功能。)代理Node.js可以异步处理大量并发连接,因此很容易用作服务器端代理人。当在具有不同响应时间的不同服务之间进行代理,或者从多个来源收集数据时,这尤其有用。举个例子:考虑一个服务器端应用程序,它与第三方资源通信以更新来自不同来源的数据,或者将服务器端的一些图像和视频资源存储到第三方云服务。虽然专用代理服务器确实存在,但如果您还没有专用代理服务器,或者您需要本地开发的解决方案,那么使用Node作为代理可能是更好的选择。关于这个方案,我的意思是当你在开发的时候,你可以使用Node.js开发环境构建一个服务来处理资源和代理的请求,而在生产环境中,你可以使用一个专门的代理服务(比如如nginx、HAProxy等)来处理这些交互。股票交易者的仪表盘让我们继续讨论应用程序。实时网络解决方案可以轻松实现股票交易软件——用于跟踪股票价格、执行计算、进行技术分析和生成报告。使用基于网络的实时解决方案将使操作员能够轻松地切换工作和位置。信不信由你,我们可能会在佛罗里达、伊比沙岛甚至巴厘岛的海滩上看到它们。ApplicationMonitoringDashboard另一个非常适合使用Node+Web+Socket的常见用例:跟踪网站访问者并可视化他们之间的实时交互。(如果您有兴趣,请查看Hummingbird。)您可能想要捕获用户的实时状态,甚至在他们到达漏斗中的某个点并进入下一个阶段时打开一个沟通渠道。(如果你有兴趣,我建议你看看CANDDi)想象一下,如果你实时知道你的访问者在做什么,并且可以可视化他们的互动促进,这会给你的业务带来多大的好处。使用Node.js进行实时双向套接字通信,现在您可以了。系统监控工具现在,让我们看看基础设施方面的事情。想象一下,例如,SaaS运营商希望为其用户提供服务监控页面(例如,GitHub上的状态页面)。通过Node.js事件循环,我们可以创建一个强大的基于Web的仪表板,它可以异步检查服务状态并使用WebSockets将数据推送到客户端。使用该技术可以实时报告内部(公司内部)和公共服务状态。让我们把这个想法更进一步,想象一下电信运营商、云/网络/服务器运营商或一些金融机构的网络运营中心(NOC)的监控应用程序,都运行在这个Node.js和WebSocket上应用程序而不是Java和/或JavaApplets。注意:不要尝试使用Node来构建硬实时系统(即需要一致响应时间的系统)。对于此类应用程序,Erlang可能是更好的选择。在何处使用Node.js服务器端Web应用程序将Express.js与Node.js结合使用也可用于在服务器端创建典型的Web应用程序。然而,尽管可能,使用Node.js以请求+响应的方式呈现HTML并不是最典型的用例。有些人赞成,有些人反对这种做法。这里有一些思路供参考:优点:如果不需要做CPU密集型计算,可以从头到尾使用Javascript甚至数据库(如MongoDB)。这显着减少了开发过程(包括成本)。对于使用Node.js作为服务器的单页应用程序或websocket应用程序,爬虫可以接收到一个完整渲染的HTML响应,这对SEO更加友好。缺点:任何CPU密集型计算都会阻碍Node.js的响应能力,因此使用多线程平台是更好的方法。或者,您也可以尝试横向扩展计算[*]。Node.js用关系型数据库还是很痛苦的(详见下文)。拜托,如果你想执行关系数据操作,请考虑其他环境:Rails、Django甚至ASP.NETMVC。...[*]另一种解决方案是为这些CPU密集型计算构建一个高度可扩展的支持MQ的环境和后端处理,从而让Node作为前端专员异步处理客户端请求。不应该使用Node.js的地方使用关系数据库的服务器端Web应用程序与Node.js和RubyonRails上的Express.js相比,在使用关系数据库时请毫不犹豫地选择后者。Node.js的关系数据库工具仍处于早期阶段,还不够成熟,人们无法愉快地使用它。同时,Rails自带了自己的数据访问组件,以及DBschema迁移的支持工具和一些Gems(一语双关,一个是指这些珍贵的工具,一个是指ruby的gems包)。Rails及其配套框架具有非常成熟和经过验证的活动记录(ActiveRecord)或数据映射(DataMapper)数据访问层实现,而这些是当您使用纯JavaScript复制这些应用程序时。真的很想用点东西。但是,如果您真的倾向于使用所有JS(并准备好发疯),请继续关注Sequelize和NodeORM2,这两者都还不成熟,但最终会迎头赶上。[*]仅使用Node作为前端,使用Rails作为后端来连接关系数据库是完全可能的,而且并不少见。(作者注:国外有种说法,像PHP这样的程序员也可以算作前端)当繁重的服务端计算和处理涉及到大量的计算时,Node.js不是最好的解决方案。你肯定不想使用Node.js来构建斐??波那契计算服务。一般来说,任何CPU密集型操作都会削弱Node通过事件驱动、异步I/O模型等方式带来的吞吐量优势,因为任何传入的请求都会被阻塞。如前所述,Node.js是单线程的,只使用一个CPU内核。对于服务端的多核并发处理,Node的核心团队利用cluster模块在这方面做了一些工作(参考:http://nodejs.org/api/cluster.html)。当然,你也可以通过nginx反向代理轻松运行多个Node.js服务器实例,避免单线程阻塞的问题。关于集群,您应该将所有繁重的计算卸载到用更合适的语言编写的后台进程,同时让它们通过RabbitMQ等消息队列服务器进行通信。尽管您的后台处理最初可能在同一台服务器上运行而没有什么明显的好处,但这样做具有非常高的可伸缩性的潜力。这些后台处理服务可以很容易地拆分为单独的工作服务器,而无需配置入口Web服务器的负载。当然,您可以在其他语言平台上使用相同的方法,但是使用Node.js可以获得非常高的吞吐量,每个请求都被非常快速高效地处理为一个小任务,这一点我们已经讨论过了。结论我们已经讨论了Node.js从理论到实践,从它的目标和抱负,到它的优势和劣势。Node.js开发中99%的问题都是由于误用阻塞操作造成的。请记住:Node.js从来不是为了解决大规模计算问题而创建的。它的出现就是为了解决大规模I/O的问题,在这一点上做得很好。综上所述,如果您的项目需求不包括CPU密集型操作并且不需要访问任何阻塞资源,那么您可以利用Node.js的优势并享受快速且可扩展的网络应用程序。原文链接:http://www.toptal.com/nodejs/why-the-hell-would-i-use-node-js翻译链接:http://blog.jobbole.com/53736/