到底什么是Reactor?我们先看看官网是怎么说的,如下:
再看看我从网上找的比较好的解释,如下:
通过上边的两个图,我们大致可以这么理解,Reactor是一个线程,这个线程在处理IO事件的时候是基于IO多路复用模型的。也就是说,这个线程是基于事件驱动的,可以处理一个或多个连接,并且将连接产生的事件交给指定的Handler处理器。归根结底,Reactor就是一种线程模型,这个线程就是EventLoop线程。
我们都知道Netty在高并发场景下性能及其优异,这得益于Netty的动力引擎——Reactor线程模型的运用。在前几篇中说过,IO多路复用机制可以实现一个线程处理多个连接,但是使用NIO的API基于IO多路复用模型开发的一套网络应用依然不能解决高并发场景所面临的问题,也就是高并发场景下依然会大量的连接不能及时得到处理而超时。
具体的原因就是IO多路复用机制中,一个处理事件的线程绑定一个选择器,它有两个阻塞点:select()和read()。这里一定要是注意这个read(),当它读不到数据的时候,它是非阻塞的;当它读到数据的时候,它就是阻塞的(也就是读取数据的时候和BIO是相同的机制,首先是内核调用系统API读盘,将数据读到内核的缓存、内核再通过系统API将缓存拷贝至用户缓存,线程唤醒)。当高并发场景,通过这一个线程处理连接产生的各类事件难免会力不从心,一旦某个连接的事件卡在read()阻塞点,势必会影响其他连接的事件处理,从而造成大量连接的超时,所以采用原生的NIO还是无法解决高并发问题。
那么Netty为什么就能解决高并发问题呢?
这就得益于Netty使用了Reactor线程模型,这个模型在原生NIO的IO多路复用的基础上做了优化,它不再仅仅使用一个线程去处理连接的事件了,而是使用一组线程去处理,也就是所谓的空间换时间,而且又把客户端连接的事件做了分类处理:
- 连接事件交给一组BOSS事件循环组处理
- 读写事件交给Worker事件循环组处理 这样的话,由原来的一个线程专注两种事件(连接事件、读写事件)改成一个线程只专注一种事件(要么连接事件,要么读写事件),这样,一个线程就可以处理更多的同类事件。
举个例子:当大量的客户端发起连接请求时,这个线程专注处理这个连接事件,处理完后,这个线程就会把这个客户端的其他事件交给其他的线程去处理,由于这个线程只处理这一个事件,那么它处理的连接事件的速度就会更快,会在更短的时间内把所有客户端的连接请求(也就是为每个客户端创建连接)都处理好,这个线程就无需担心某个客户端连接的read事件的阻塞而影响其他客户端连接请求的处理。
Netty支持单Reactor单线程、单Reactor多线程、主从Reactor多线程三种线程模型。
单Reactor单线程,如图:
单Reactor多线程,如图:
主从Reactor多线程,如图:
以上就是三种Reactor模型的图解,我相信大家能看出区别,单Reactor单线程表示Boss只有一个事件循环,Worker也只有一个事件循环;单Reactor多线程是Boss只有一个事件循环,Worker有多个事件循环;出从Reactor多线程是Boss有多个事件循环,Worker有多个事件循环。