1. Reactor出现的原因
Reator模式是大多数IO相关组件如Netty、Redis在使用时的IO模式,为什么需要这种模式,如何设计来解决高性能并发的呢?
最最原始的网络编程思路就是服务器用一个While循环,不断监听端口是否有新的套接字连接,如果有,就调用一个函数处理,类似:
while(true){ socket=accept(); handle(socket) }
这种方法最大的问题是无法并发,效率太低,如果当前的请求没有处理完,那么后面的请求只能被阻塞,服务器的吞吐量太低。
之后想到了使用多线程,也就是很经典的connection per thread,每一个连接用一个线程处理,类似:
while(true){ socket=accept(); new thread(socket); }
Tomcat服务器的早期版本也是这么实现的。多线程的方式确实一定程度上极大的提高了服务器的吞吐量,因为之前的请求在read阻塞以后,不会影响后续的请求,因为他们在不同的线程中。这也是为什么通常会讲“一个线程只能对应一个socket”的原因。
其实一个线程中创建多个socket 语法上是可以的,但是实际上没用,一个线程里只能处理一个socket,就算accept多个也没有用,前一个socket被阻塞了,后面的是无法被执行到的。
缺点在于资源要求太高,系统中创建线程是需要比较高的系统资源的,如果连接数太高,系统无法承受,而且线程的反复创建-销毁也需要代价。
线程池本身可以缓解线程创建-销毁的代价,这样优化确实会好很多,就是线程的粒度太大。每一个线程把一次交互的事情全做了,包括读取和返回,甚至连接,表面上似乎连接不在线程里,但是如果线程不够,有了新的连接,也无法得到处理,所以目前方案的线程里可以看成要做三件事:连接/读取/写入。
线程的粒度太大了,限制了吞吐量。应该把一个线程做的3件事拆分为更细的粒度,这些更细的粒度就是更小的线程。整个线程池的数据会增加很多,但是线程更简单,任务更单一。这其实就是Reactor出现的原因。
以上学习自:高性能IO之Reactor模式 - 时间朋友 - 博客园
感谢这篇博客作者,让我了解了Reactor出现的原因。
在Reactor中,这些被拆分的小线程或者子过程对应的是handler,每一种handler会处理一种event.
2. 什么事Reactor模式?
Reactor模式首先是事件驱动的,有一个或多个兵发输入源,有一个Service Handler,有多个Request Handler,这个Service Handler会同步的将输入的请求(Event)多路复用的分发给相应的Request Handler.
用图来表达:
从结构上看,这有点类似生产消费者模式,即有一个或多个生产者将事件放入一个Queue中,而一个或多个消费者主动的从这个Queue中的Poll事件来处理;而Reactor模式则没有Queue来做缓冲,每当一个Event输入到Service Handler之后,该Service Handler会主动的根据不同的Event类型将其分发给对应的Request Handler来处理。
3. Reactor模式结构
第2点学习并摘抄自:http://www.blogjava.net/DLevin/archive/2015/09/02/427045.html