reactor模型和nodejs的实现

reactor

同步,异步,阻塞,非阻塞

Synchronous IO: operatins causes the requesting process to be blocked until that io operation completes.
Asychronrous IO: operations that does not cause the requesting process to be blocked.
阻塞:程序会自己挂起等待结果。
非阻塞:如果数据没有准备好,程序不关系结果直接返回。需要程序自己回去检查数据是否就绪。

简单来讲,同步针对的是程序和kernel的通信。如果一个操作会返回结果(数据准备好或者没准备好),那么这个call就是同步的。反之,如果一个call不返回结果(我不知道数据怎么样,需要kernel自己回调函数),那么这个call就是异步的。
所以,同步可以阻塞也可以非阻塞,看程序本身如何应对返回结果(是直接从kernel拷贝数据还是先返回)。
异步只能非阻塞(因为异步表示kernel会将所有东西准备好然后回调函数,所以不存在call需要等待的情况)。

如果一个call需要自己去查询数据是否就绪,则一定为同步(epoll很tricky,虽然运用了callback,但仍旧需要epoll_wait去检查,所以是同步的)
select/poll/epoll都是同步。
如果epoll_wait(timeout)timeout=-1,阻塞(知道捕获到信号)。timeout=0,非阻塞,直接返回。timeout>0阻塞n毫秒。

总结,IO call分为两步

  1. 询问数据是否就绪。
  2. 将数据从kernal拷贝到进程。
    同步异步针对两个步骤,任何一个阻塞,都为同步。
    阻塞非阻塞针对步骤1,步骤二不理会。

reactor的特点

  1. 事件驱动
  2. 处理多个输入源
  3. 通过service handler同步的将输入事件(event)采用多路复用(select/poll/epoll)分发给相应的request handler同步的将输入事件(event)采用多路复用(select/poll/epoll)分发给相应的request handler处理。

单线程reactor:一个线程来处理连接,读写,计算。消息的处理被放到独立的handler中。


多线程reactor:为handler开启不同的县城。


主从reactor模型:main reactor针对连接,subreactor针对io操作。

nodejs


由上图可知,nodejs包括顶层的javascript(程序员层面)和底层的V8, libuv(底层io实现)。
JS层面,程序是同步阻塞单线程的。如果语句出现问题,则整个程序卡住。
事件循环函数会不断检查事件队列中有没有需要处理的时间,直到程序结束。此循环对开发者不可见,由libuv实现。
libuv是一个底层的用c实现的异步io库。通过主线程检查事件队列,线程池来处理不同handler。

nodejs编写简单,处理并发时有独特的优势。然而,当某需求需要在js上大量的cpu计算时,单线程的劣势就体现出来了。