nodejs学习日志4--异步IO

初识异步是在ajax的请求中,node是首个将异步作为主要编程方式和设计理念的。

      B/S模型中,前端通过异步请求资源可以消除UI阻塞的现象,但是前端获取资源的速度也取决于后端的响应速度。例如请求两个资源A和B,A需x,B需y,同步的情况下需要时间是x+y,异步的情况下就是max(x,y),取决于时间长的请求,A不阻塞B,B不依赖A的结束。在分布式情况下同步和异步的差异会更大,且不说CPU的各级缓存和内存的I/O,网络I/O和磁盘I/O都是非常耗时的操作,所以异步I/O就显得非常重要。后端的资源响应速度的快慢直接影响到前端的用户体验。

       在计算机资源中,通常I/O与CPU计算之间是可以并行进行的,单线程同步编程模型会因阻塞I/O导致硬件资源得不到更优利用,多线程又面临死锁,状态同步等问题,而node正是利用单线程和异步I/O,但是单线程无法利用多核CPU(?),另外阻塞I/O造成CPU等待浪费,非阻塞需要轮询去确认数据是否完全 获取,它会让CPU处理状态判断,对CPU也是浪费,轮询技术的演进:

  • read
  • select
  • poll
  • epoll
  • kqueue(freebsd系统下)
select和epoll比较形象的对比可以参考 http://weibo.com/1711278761/zpzMyhndl

轮询技术满足了非阻塞I/O确保数据的完整的需要,但应用程序依然需要花费时间等待完全数据的返回,等待期间CPU也得不到充分利用。

node的异步I/O:事件循环,观察者,请求对象,I/O线程池这四者共同构成了node异步I/O模型的基本要素,window下通过IOCP来向系统内核发送I/O调用和从内核获取已完成的I/O操作,配以事件循环完成异步I/O过程。在Linux下通过epoll实现这个过程,FreeBsd下通过kqueue实现,不同的是线程池在Windows下由内核(IOCP)直接提供,×nix系列下有libuv自行实现。nodejs学习日志4--异步IO

       node是单线程的,这里的单线程仅仅是JavaScript执行在单线程中,内部完成I/O任务另有线程池,node自身其实是多线程的,只是I/O线程使用的CPU较少。除了用户代码无法并行执行,所有的I/O是可以并行起来的。



转载于:https://my.oschina.net/ozil/blog/186810