Node.js 应该用在什么地方
聊天
聊天是最典型的多用户实时交互的应用。从IRC开始,有许多开源或者不开源的协议都运行在非标准端口上,而现在,使用 Node.js 则可以解决这些问题——在标准的80端口运行 WebSockets。
聊天应用程序是最能体现 Node.js 优点的例子:轻量级、高流量并且能良好的应对跨平台设备上运行密集型数据(虽然计算能力低)。同时,聊天也是一个非常值得学习的用例,因为它很简单,并且涵盖了目前为止一个典型的 Node.js 会用到的大部分解决方案。
让我们试着来描绘它如何工作。
在最简单的情况下,我们布置了一个聊天室在我们的网站上,用户可以在上面发消息,当然是一对多的形式。例如,假设总共有三个人连接到我们的网站上。
在服务端这边, 我们有一个使用 Express.js 搭建的简单站点,该站点实现了两件事 1) 处理路径为 ‘/’ 的GET请求时,下发包括一个留言板以及一个发送信息的 ‘发送’ 按钮的页面 2) 一个监听客户端发送新消息的 websockets 服务。
在客户端这边,我们有一个 HTML 页面,上面有个两个 js 方法,一个是用于触发事件的 “发送” 按钮,这会把把输入的消息通过 webscoket 发送,另一个方法是用 webscoket 在客户端上监听服务端来的推送(例如,其他用户发送的消息)。
当有一个客户端发送消息的时候,发生的事情是:
- 浏览器上,点击发送按钮触发了 js 函数,将输入框中的文字通过 websocket 消息发送到服务器的 websocket 客户端(页面初始化加载的时候连接的)。
- 服务端的 websocket 组件收到 消息,然后通过广播方法转发到其他所有连接的客户端。
- 通过页面上运行的 websocket 客户端组件,所有的客户端都能收到这条推送的新消息。接着 js 处理函数可以把这个消息添加到文字框内。
这是一个最简单的例子。如果要更好的解决方案,你可以使用 Redis 数据库做一个简单的缓存。在一个更高级的解决方案中,你可能需要一个消息路由来专门处理消息队列,并且需要一个更强健的发送机制,比如发送的时候覆盖上暂 时离线的用户或者为离线的注册用户存储尚未接收的消息等等。但是不论你做了怎么样的改进,Node.js 都将遵循一个基本原则:响应事件,处理多个并发连接,并保持流动性的用户体验。
对象数据库接口(API ON TOP OF AN OBJECT DB)
尽管,Node.js 确实非常擅长实时交互的应用,同时它也十分适合通过对象数据库(object DB)来查询数据(如 MongoDB)。以 JSON 格式存储的数据允许 Node.js 直接处理,不需要纠结数据转换和匹配的问题。
举个例子,如果你正在使用 Rails,你会将 JSON 数据转成 二进制的 model,当数据再被 Backbone.js, Angular.js 或者 jQuery AJAX 之类的调用又要转回 JSON。如果是 Nodejs 的话,你可以通过一个 REST API 简单的导出 JSON 对象以供客户端使用。另外,从数据库读写时候如果使用的是 MongoDB 的话,你也不用担心的 JSON 与任何数据之间的格式问题。总之,你可以避免多元的数据转换问题,不论是在客户端、服务端还是数据库。
队列输入
如果你正在接收一个高量并发的数据,你的数据库可能会成为你处理的瓶颈。正如上面的描述,Node.js 可以轻松的处理并发连接。 但是,由于数据库操作是一个阻塞的操作(在这种情况下),这就是麻烦的地方。Node.js的解决方案是,在数据真正的写入之前就承认客户端的数据是真实 的。
用这种方法,在高负载的时候系统继续维持它的响应,这在当客户端不需要严格确认一个数据是否成功的被写入时特别有用。典型的例子包括:日志记录或者用户跟踪数据(user-tracking data)的记录,这会被分批处理并且在稍后才使用;同时也包括最终一致性(so, 常用于 NoSQL)可以接受,不需要立即反应的操作(例如 Facebook 上更新点赞的数目)。
数据通过某些缓存或者消息队列的基础组件(例如 RabbitMQ, ZeroMQ)进入队列,并且通过一个独立的数据库批量写入进程来一一消化,或者通过一个更高性能的计算密集型后端服务来进行处理。其他的语言/框架也可 以实现相似的操作,但在相同的配置下是达不到 nodejs 的高吞吐量与高并发。
简单的说:使用 Node,你可以把数据库操作扔到一边并在稍后处理它们,假设他们成功了一样继续执行下去。(笔者注:在开发中通常的情况通常是,种耗时的操作通过回调函数来异步处理,主线程继续往下执行)
数据流
在较为传统的网络平台上,HTTP 的请求和响应更像是孤立的事件;然而事实上,他们都是数据流。这一观察结果在 Nodejs 上可以用来建立一些很酷的功能。因为数据通以流的形式接收,而我们可以在网站上在线处理正在上传中的文件。这样的话,就可以实现实时的音频和视频编码,以及在不同数据源之间进行代码(代理见下一段)。
(笔者注:Node 有代替如 apache 这样的 webserver 处理数据,所以开发者可以直接收到客户端一份一份上传的数据,并实时处理。上面这段话听起来有点抽象,不过各位可以简单的想象一下不需要开 YY 或者 QQ,打开网页就能进行语音视频的功能。)
代理
Node.js 可以通过异步的方式处理大量的并发连接,所以很容易作为服务端的代理来使用。这在与不同响应时间的不同服务之间进行代理,或者是收集来自多个来源的数据时尤其有用。
举个例子:考虑一个服务器端的应用程序和第三方资源进行通信以更新自不同来源的数据,或者将服务端上的一些图像和视频资源存储到第三方云服务。
虽然专用代理服务器确实存在,但是如果你还没有专用的代理服务器,或者你需要一个本地开发的解决方案,那么使用 Node 来做代理可能是更好的选择。关于这个解决方案,我的意思是指当你在开发的时候,你可以使用Node.js的开发环境搭建一个服务来处理对资源和代理的请 求,而在生产环境下,你可以使用专用的代理服务(比如nginx,HAProxy等)来处理这些交互。
股票操盘手的仪表盘
让我们继续讨论应用程序这块。实时网络的解决方案可以很轻松的实现证券交易软件——用于跟踪股票的价格,执行计算、做技术分析,同时生成报表。
使用一个实时的的基于网页的解决方案,将会允许操盘手轻松的切换工作软件以及工作地点。相信不久,我们或许会在 佛罗里达州、伊维萨岛又或者是巴厘岛的海滩上看到他们。
应用监听仪盘表
另一种常见的用例中,使用 Node+Web+Socket 非常适合:跟踪网站访问者并且可视化实时它们之间的实时交互。 (如果你有兴趣,可以去看看Hummingbird)
你可能需要采集用户的实时状态, 或者甚至当他们到达渠道中某个特定的点时, 打开一个交流频道, 通过有针对性的互动介绍移动到下一个阶段. (如果你感兴趣的话,推荐你看看 CANDDi)
想象一下,如果你知道你的访客的实时操作,并能够形象化地看到他们的交互,这将对你的业务带来多大的提升。随着实时的、双向 socket 通信的 Node.js ,现在你可以做到了。
系统监控仪表
现在,让我们看看事情的基础设施方面。想象一下,比如,希望为其用户提供服务监控页面(例如,GitHub上的状态页)的 SaaS 运营商 。通过 Node.js 的事件循环,我们可以创建一个基于 Web 的功能强大的仪表板,以异步方式检查服务状态并且使用的 WebSockets 将数据推送到客户端。
内部(公司内部)和公共服务的状态都可以使用该项技术实现实时的上报。让我们把这一想法延伸的远一点,试着想象一个电信运营商中网络运营中心(NOC)的监控应用,云/网络/服务器运营商,或者一些金融机构,全都运行在这个由 Node.js 和 WebSocket 组成的应用上,而不是 Java 和/或 Java Applet。
注意:不要尝试使用 Node 打造硬实时系统(即,响应时间要求一致的系统)。 Erlang是可能是该类应用程序的更好的选择。