大神Doug Lea在http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf 里详细介绍了java nio的实现思路,里面也详细介绍了reactor模式,后文统一称为老爷子的文章。
看这篇文章建议先了解下linux中的文件描述符与套接字socket redis中的IO多路复用select和epoll
传统阻塞I/O模型

以上图片摘自大神Doug lea 的nio。
特点
-  一个后端线程只能处理一个客户端请求 
-  采用I/O阻塞的模式处理客户端请求 
分析
-  随着并发量上升,后端资源有限的情况下会占用大量的线程资源; 
-  如果后端资源有限,那么后面来的客户端请求会阻塞; 
-  线程的创建和销毁也会占用大量的cpu资源; 
改进
- 可以引入线程池,减少线程的重复创建和销毁
reactor模式
在https://en.wikipedia.org/wiki/Reactor_pattern中。
梳理下关键点:
-  是一种事件驱动处理模式 
-  处理一个或多个输入并发请求 
-  服务器通过handler对请求进行多路分发,分发给request handlers 
在上一篇中讲了I/O多路复用,
在老爷子的文章里对reactor pattern有如下说明:
-  reactor 通过分发IO事件给对应的handler处理; 
-  handlers执行非阻塞操作 
-  通过绑定处理器handlers处理对应的事件进行管理(这个就是acceptor) 
然后老爷子又分了三种reactor模式
单线程reactor模型,也是最基本的reactor模式

java nio是这么支持的
-  channels 连接到支持非阻塞读取的文件、socket等 
-  buffers 可以被channels读取或写入的缓冲区 
-  selectors 识别出哪个channels中有io事件 
-  selectionKey io事件状态和处理器的绑定 
老爷子在文档里也举了一个例子,这里不再说明。
-  这个模式里,reactor负责分发(dispatch) 
-  然后由启动Acceptor调用对应的Handler 
-  由Handler进行网络io读、业务处理,网络io写; 
redis5.0之前都是使用类似这种模式;
-  aeMain进行loop 
-  aeProcessEvents进行事件捕获与分发 
-  通过aeApiPoll 捕获事件 
-  通过事件类型掩码mask进行事件处理(分发即处理) 
-  通过fe->rfileProc和fe->wfileProc 执行然后又重新注册新的事件 
单reactor多线程处理

-  在这个模式里reactor只负责分发 
-  业务逻辑都交给了线程池处理 
在这个模式里reactor还是单线程,不过reactor获取到的任务会分发给线程池处理(redis中实现时,主线程也是一条工作线程)
redis6.0使用这种模式的变种
-  aeMain进行loop 
-  aeProcessEvents进行事件捕获与分发 
-  通过fe->rfileProc和fe->wfileProc 执行然后又重新注册新的事件 
-  通过aeApiPoll 捕获事件(就是上一篇讲的IO多路复用机制) 
-  捕获后分发给线程池(轮询分发) 
-  线程池处理分发的任务(主线程是线程池第一个线程) 
-  通过fe->rfileProc和fe->wfileProc 执行然后又重新注册新的事件 
-  主线程等待所有的线程处理完,然后进入下一个轮询 
多reactor多线程处理

nginx应该是使用这种模式
最后奉上之前画的io处理流程图

redis系列文章
redis源码阅读-入门篇
redis源码阅读二-终于把redis的启动流程搞明白了
redis源码阅读三-终于把主线任务执行搞明白了
redis源码阅读四-我把redis6里的io多线程执行流程梳理明白了
redis源码阅读五-为什么大量过期key会阻塞redis?
redis源码六-redis中的缓存淘汰策略处理分析
阅读redis源码的时候一些c知识
linux中的文件描述符与套接字socket
redis中的IO多路复用select和epoll
redis的key过期了还能取出来?










