http://www.raychase.net/282
传统服务器接收到请求以后,从request到response,整个过程占住一个线程不放,但是这种服务器可以在收到请求之后,将需要完成的工作用一个或若干个Command包装好,交给线程池中的工作线程去完成,对于收到请求和返回响应这样的过程,使用1~2个独立的线程去完成,在事件发生时,系统线程才通知这1~2个线程去完成和客户端的一次交互(或者用监控线程去轮询当前挂在Server上所有的连接,寻找需要响应的连接来完成交互)。
当在线用户数量大大超出服务器的线程数时,使用NIO模式可以保证在收到请求和返回响应的用户接口层不成为瓶颈 。
另外还有一个特别值得一提的场景,由于互联网的BS模式下,从Server实时或准实时地向Client推送一些东西是比较麻烦的(有同学说用pushlet来解决,但这个办法有很大的局限性),有一种解决这个问题的办法是客户端使用ajax去定期获取数据(比如现在的很多SNS网站都用了这种办法),在这种情况下服务端对请求处理的压力就陡然增大了。
Nginx是一款高性能的代理服务器,性能高的其中一个重要原因是,它基于epoll模型设计的。与之相对的是select模型,select采用的是轮询的办法,每次读写状态检测都检查FD_SET中所有的句柄,当句柄数量增大时,这个过程消耗的时间应该是线性增长的。另外,FD_SIZE也设定了整个可开启的句柄数,这造成了另一种局限。
epoll模型就没有这两个问题,它给每个活跃FD挂接一个异步回调函数,不需要第三方去遍历和调用这些句柄,而它的句柄限制是操作系统的限制 。
关于Continuation Server。这种模式下Client和Server会调过来,Continuation Server发送页面给客户端,作为function call,然后等待客户端返回执行结果(SendPageAndWait),因此,在服务端收到响应的时候,要恢复之前方法调用的上下文环境,继续执行收到响应后的下一行语句 。
这个过程就需要服务器端能够在发送页面前将上下文环境保存下来,在获得响应之后动态获取调用栈恢复上下文环境,这些工作都是异步事件驱动的。
Node.js所有的事件触发的调用都是异步和非阻塞的,它对高并发的访问有很好的承受能力(Node宣称他们的服务器每一台都可以承受几万连接并发)。如果服务端面对一场subscribe的灾难,虽然有足够大的队列来承受瞬间的高并发访问,但是瓶颈在请求接收和响应上,那么Node.js应该能成为一个有价值的解决方案。
最后,对于Jscex,还有Barrier模式,在此不展开。
异步调用给传统软件编码的思维带来了新的挑战,无论是对现场的快照、异常的处理还是分支跳转的控制,但是带来了许多不可替代的优势,资源占用更少,效率更高,可扩展性更强。
The fd_set structure is used by various Windows Sockets functions and service providers, such as the select function, to place sockets into a "set" for various purposes, such as testing a given socket for readability using the readfds parameter of theselect function.
typedef struct fd_set { u_int fd_count; SOCKET fd_array[FD_SETSIZE]; } fd_set;