可能大多数人都了解传统的服务端编程的I/O模型,就像1.2节那个“阻塞”的jQuery例子一样。下面是一个PHP的例子: 这段代码做了些I/O操作,并且在所有数据回来之前,这个进程会被阻塞。对于很多程序而言,这个模型没什么问题,并且很容易理解。但有一点可能会被忽略:这个进程也有状态,或者说内存空间,并且在I/O完成之前基本上什么也不会做。根据I/O操作的延迟情况,那可能会有10ms到几分钟的时间。延迟也可能是由下列意外情况引发的: 硬盘正在执行维护操作,读/写都暂停了; 因为负载增加,数据库查询变得更慢了; 由于某种原因,今天从sitexyz.com拉取资源非常迟缓。 如果程序在I/O上阻塞了,当有更多请求过来时,服务器会怎么处理呢?在这种情景中通常会用多线程的方式。一种常见的实现是给每个连接分配一个线程,并为那些连接设置一个线程池。你可以把线程想象成一个计算工作区,处理器在这个工作区中完成指定的任务。线程通常都是处于进程之内的,并且会维护它自己的工作内存。每个线程会处理一到多个服务器连接。尽管这听起来是个很自然的委派服务器劳动力的方式(最起码对那些曾经长期采用这种方式的开发人员来说是这样的),但程序内的线程管理会非常复杂。此外,当需要大量的线程处理很多并发的服务器连接时,线程会消耗额外的操作系统资源。线程需要CPU和额外的RAM来做上下文切换。 为了说明这一点,我们来看NGINX和Apache的一个基准比较(见图1-2,源自http://mng.bz /eaZT)。或许你还不了解NGINX(http://nginx.com/),它跟Apache一样,是个HTTP服务器,但它用的不是带有阻塞I/O的多线程方式,而是带有异步I/O的事件轮询(就像浏览器和Node一样)。因为这些设计上的选择,NGINX通常能处理更多的请求和客户端连接,它因此变成了响应能力更强的解决方案 。 图1-2 WebFaction Apache/NGINX基准比较 在Node中,I/O几乎总是在主事件轮询之外进行,使得服务器可以一直处于高效并且随时能够做出响应的状态,就像NGINX一样。这样进程就更加不会受I/O限制,因为I/O延迟不会拖垮服务器,或者像在阻塞方式下那样占用很多资源。因此一些在服务器上曾经是重量级的操作,在Node服务器上仍然可以是轻量级的。 这个混杂了事件驱动和异步的模型,加上几乎随处可用的JavaScript语言,帮我们打开了一个精彩纷呈的数据密集型实时程序的世界。
Node.js实战——1.3 异步和事件触发:服务器
书名: Node.js实战
作者:
出版社: 人民邮电出版社
原作名: Node.js in Action
译者: [美] Mike Cantelon | [美] TJ Holowaychuk | [美] Nathan Rajlich
出版年: 2014-5
页数: 356
定价: 69.00元
装帧: 平装
ISBN: 9787115352460