node chat源码解读(三)
程序即server
传统的web服务通常是把提供HTTP协议支持的前端server与背后承担业务逻辑的程序分开的。比如用PHP写成的wordpress只是程序,它的前段一定要架设一个nginx,或者apache,或者其他的web server才能提供服务。
这一模式显然有他与生俱来的优势——把协议层和应用层隔离开了。程序开发者只需要关心业务代码的开发,而不用或者很少去关心协议层的实现。而且,在大多数情况下,同样的应用层代码可以在不同的web server上正确地工作。同样地,协议层的web server开发者只需要专心实现好协议层的功能即可,而不需要也无法照顾业务层的功能。
这种模式使得隔离后的双方都更专注,催生了一批优秀的开源软件,如server端的nginx,apache和lighttp等;即便在需求复杂多变的应用端,也诞生了不计其数的优秀作品。
也正因为上述server与程序分离的原因,多次HTTP请求之间很难通过server建立高效的数据共享通道,对于读请求远多于写请求的系统来说,业务端程序需要反复地读取很少变动的数据,不仅性能不好,而且给后端存储带来了不必要的压力。尤其是这种分离直接导致了对连接池的支持乏力。
尽管后来在二者之间出现了一些借助共享内存实现的数据共享机制(如apc),甚至有些对性能有较高要求的团队通过给http server写module的方式定制化地满足了请求之间的数据共享,但双方配合方式没有实质性的改变。
而nodejs由于自身直接提供了http服务的module(或者说框架),因而开发者能很容易地写出一个协议层面的HTTP Server。将http server与程序逻辑写在一起是如此地容易,那么前端还要什么web server呢!
这一做法绝不是噱头。在这种方式下,数据能够很容易地在请求之间共享,对连接池的支持也似乎不是一件值得炫耀的事情了。
异步IO与事件机制
异步IO这一特性并没有在node chat中得到足够的体现,但却是nodejs不得不提的一个特性。这一特性把浪费在IO等待上的CPU时间充分地”压榨”了出来,在一定程度上能够降低程序的响应时间。
但是,异步总会使得程序更复杂,非必要情况下我们不建议使用。而nodejs中采用事件机制来降低由此带来的程序复杂度,不能不说是绝妙的组合。
如水所述,我们可以大致地概括出,在nodejs模式下,一个提供web服务的“程序”的一些基本的设计思路:
- 在http server中用连接池来保护外部资源;
- 很少改变的数据作为“静态”变量“缓存”在http server层,通过定时器或者外部接口进行更新;
- 对外部资源的读写采用异步IO+事件绑定的方式实现CPU时间的零等待。