REST 风格几乎是为 HTTP 协议量身定做的,在 HTTP 协议中用 URI 来标识唯一的资源,用 GET、PUT、POST、DELETE 等动词来操作资源,HTTP 协议是无状态协议,可以通过 Cache 来提高性能。本文将使用 ">Node.js 开发一个基于 JavaScript 的 RESTful 应用。
在 Web2.0 盛行的今天,作为一种可以运行在浏览器客户端的轻量级脚本语言,JavaScript 被越来越多的开发人员所熟悉和掌握。大家印象中的 JavaScript 是简单高效的,
运行在客户端的程序,甚至有人认为 JavaScript 只是一个“小玩意”。Node.js 的出现彻底颠覆了以往对 JavaScript 的看法。Node.js 是服务器端的 JavaScript 运行环境,它的设计初衷是以一种简单的方式创建可伸缩性的网络程序。Node.js 具有异步 I/O 和事件驱动等特性,充分利用了 JavaScript 的闭包特性和事件处理机制,实现了类似 Apache 的 HTTP Server,使之具备了构建基于 JavaScript 的高并发的 Web Application 的能力。在 Node.js 的官方网站中使用 Node 来表示 Node.js,本文也将沿用这种用法,后文中出现的 Node 等同于 Node.js。
Node.js 的异步 I/O 和事件驱动机制
首先解释一下所谓的同步 I/O 和异步 I/O 的概念。它们都是针对于应用程序而言。
同步 I/O 指的是应用程序在遇到 I/O 操作时进入等待,不能利用 CPU,直到 I/O 操作结束后应用程序才继续执行后续任务。 异步 I/O 指的是应用程序在遇到 I/O 操作时不等待,继续执行后续任务,等 I/O 操作结束后操作系统发出事件提醒应用程序。
可以看出异步 I/O 能够更好地利用 CPU,提高应用程序的执行效率,同时提高 I/O 的并发性。举例来说,应用程序要先后执行两个 I/O 任务,网络 I/O 和文件 I/O,在同步 I/O 模型中应用程序必须等网络 I/O 执行完成后,才能执行文件 I/O。在异步 I/O 模型中,应用程序执行了网络 I/O 任务之后,不需要等待网络 I/O 的结束,可以立即执行后续的文件 I/O,从而使得 I/O 并发。
下例展示了用 Node 来打开一个文件的异步 I/O 的执行过程。主线程在执行了文件 I/O 后不等待,直接执行后续程序,I/O 执行结束后自动执行回调函数。
清单 1. 异步文件 I/O
// 加载 fs module fs = require('fs'); // 打开 example.log 文件 fs.open('c:/example.log', 'r',
function(){ // 在回调函数中对文件进行操作 console.log('Open file completed!'); }); console.log('Execute main thread!');
图 1. 异步文件 I/O 执行结果
Node 的异步 I/O 特性很好地提高了对请求的并发处理能力,这点在 Web 服务器领域非常重要。传统的 Web 服务器比如 Apache HTTP Server,采用的是同步 I/O 的模型,通过多线程的方式来实现对请求的并发处理。基于线程的模型相对来说没有那么高效,并且要处理公共资源同步问题,对连接数也有一定的限制,服务器要给每个连接分配线程栈空间存储局部变量,对服务器的内存开销很大。Node 采用的是单线程 + 异步 I/O+ 事件轮询的机制来处理请求并发的。Node 用一个主线程来监听服务器的请求,有请求到达就用异步 I/O 处理请求,同时主线程能够快速的执行完毕来处理下一个请求。Node 后台通过事件轮询去监听 I/O 的处理情况,当 I/O 完成后,Node 会根据事件驱动机制去调用相应的回调函数。值得注意的是 JavaScript 的闭包特性保证了回调函数执行时依然处在之前的执行上下文中,可以取到正确的变量的值。
Node 的一个最佳实践是内存操作始终快于 I/O 操作。Node 的异步 I/O 机制使它在内存中并发处理多个 I/O 请求,而不是等待 I/O 请求的串行操作。有实验证明在相同的服务器硬件条件下,Node 的并发处理能力高于 PHP/Apache 的并发处理能力。
当 PHP/Apache 3187 请求 / 秒 Node.js 5569 请求 / 秒
RESTful 应用的特点
REST 并不是一种具体的实现技术,而是一种软件架构风格,主要有以下特点:
从资源的角度来考察整个网络,每个资源有唯一标识 使用通用的连接器接口操作资源 对资源的操作不会改变资源标识 连接协议具有无状态性 能够使用 Cache 机制来增进性能
REST 风格几乎是为 HTTP 协议量身定做的,在 HTTP 协议中用 URI 来标识唯一的资源,用 GET、PUT、POST、DELETE 等动词来操作资源,HTTP 协议是无状态协议,可以通过 Cache 来提高性能。
基于 REST 的架构风格,人们把它使用到了 Web 服务中。在目前主流的三种 Web 服务实现方案中,RESTful 的 Web 服务比基于 SOAP 和 XML-RPC 方式的 Web 服务更加简洁高效。它直接使用 HTTP 协议就可以实现 Web 服务,不需要额外的封装协议和远程进程的调用。资源的表现形式可以是 HTML,也可以是 XML,JSON 等其他数据形式,这取决于 Web 服务的消费者是人还是机器。
表 1. HTTP 请求在 RESTful Web 服务中的典型应用
资源 GET PUT POST DELETE 一组资源的 URI,比如 http://www.example.com/resources/ 列出 URI 及该资源组中每个资源的详细信息 使用一组给定的资源替换当前整组资源 在本组资源中创建 / 追加一个新资源 删除整组资源 单个资源的 URI,比如 http://www.example.com/resources/1
获取给定资源的详细信息 替换 / 创建指定的资源,并将其追加到相应的资源组 把指定的资源作为资源组,并在其下创建 / 追加一个新元素,使其隶属于当前资源 删除指定元素