Reactor主从模型你理解对了么?

Posted 大帅的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Reactor主从模型你理解对了么?相关的知识,希望对你有一定的参考价值。



目录

简单回顾reactor三种模型,以及论文参考

主从reactor模型的理解

本篇文章大概1800字,阅读时间大约8分钟,本文不长,简单复习,主要是对前面的一个总结,尤其是对主从模型的理解,对可能的疑问进行说明。

Reactor主从模型你理解对了么?

01

简单回顾reactor模型


先看它的单词意思:

Reactor主从模型你理解对了么?

顾名思义,它的本质就是一个能及时对I/O事件进行反应的线程(进程),一般是写在循环里,类似:while(true){selector.select();...},被一个线程驱动,它会源源不断的轮询出I/O事件,所以称作反应堆(reactor)很贴切。


常见的reactor模型有三类:

1.单线程模型

Reactor主从模型你理解对了么?

acceptor作为新连接的接受者,handler负责处理各个网络连接,它们都在一个线程中执行。看起来线程数很少,很高效,但是这个模型的缺陷是其中某个handler阻塞会导致其他所有的client的handler都得不到执行,并且更严重的问题是,当N个handler长时间阻塞,会导致整个服务不能接收新的外部请求(因为acceptor也被阻塞了)。因此单线程Reactor模型用的比较少。


2.多线程模型

Reactor主从模型你理解对了么?

多线程模型与单线程模型的区别是多线程reactor模型的acceptor是一个单独的线程,即Acceptor线程只用于监听客户端连接请求。具体的处理工作交给一组特定的NIO线程来负责各个客户端连接的I/O操作,每个客户端连接都与一个NIO线程绑定,因此在这个客户端连接中的所有I/O操作都是在同一个线程中完成。客户端连接有很多,但是NIO线程数比较少,一个NIO线程可以同时绑定到多个客户端连接中,它们属于一对多的关系


3.主从多线程模型

Reactor主从模型你理解对了么?

如果服务器需要同时处理海量的客户端连接,或需要在客户端连接时进行一些权限的检查,那么单线程的acceptor很有可能就处理不过来,造成大量的客户端不能连接到服务器。Reactor的主从多线程模型就是在这样的情况下提出的,它的特点是服务器接收客户端的连接请求不再是一个线程,而是由一个独立的线程池组成,同样的handler处理也由一个单独的NIO线程池负责。事实上,一般情况下Reactor的多线程模型已经可以很好的工作了,因为处理新连接的I/O线程做的事情非常轻量,把新连接封装扔给worker线程池就可以了,其他活儿不干,顶多加个登录验证,影响微不足道,故主从模型用的也不多,没必要。


Netty就是用的第二种——Reactor多线程模型,不要误以为Netty使用了Reactor主从模型。Netty是这样设计的:

1、一般情况下,服务器感兴趣的I/O事件一般分为新连接到达事件、某个连接上的I/O可读事件和I/O可写事件。Netty把新连接到达事件单独用一个线程处理,即充当主Reactor线程的角色,而I/O可读和I/O可写事件放到另外的一组NIO线程里处理,即从Reactor线程


2、这个从Reactor线程数量是怎么设置的呢?

Netty是将其默认的设置为了2倍的CPU核数个,主要是考虑到这些客户端连接上的任务都是I/O任务为主,属于I/O密集型操作,行业内经过验证的做法是将负责I/O密集型任务的线程池的大小设置为2倍CPU核数即够用了。如果涉及到不够用的情景,需要额外压测计算。


3、模型的运行规则:在运行时主Reactor只处理accept事件,新连接到来马上按照一定策略,将其转发给从Reactor线程池,在该线程池中按照策略挑选一个线程来处理这个新连接上的I/O事件,故主Reactor的开销非常小,也不会阻塞。而每个子Reactor可以管理多个网络连接,负责这些连接的I/O读和I/O写,因为是NIO,所以也不会阻塞,如果某连接上有非I/O的耗时业务逻辑,那么NIO线程在读到完整的网络消息后,将其丢给非I/O线程池处理,处理完后复杂业务逻辑的响应消息一般会放到一个响应队列,从Reactor会按照一定策略去处理响应队列,然后将消息写回客户端。


对应到JDK,也就是ServerSocketChannel只绑定到了Netty的bossGroup(NioEventLoopGroup)中的一个线程,因此在调用JDK的Selector.select处理客户端的连接请求时,实际上是在一个线程中处理的。所以对只有一个服务端口的应用,bossGroup设置多个线程也没有什么用,反而还会造成资源浪费,这也是一个编码原则——Netty boss线程一般就设置为1即可。


可以参考论文

http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf


02

对主从模型的理解


前面说了,单线程reactor模型,全程只有一个线程处理所有的客户端新连接,新连接上的I/O事件等,而多线程reactor模型是用一个线程去接收所有的客户端新连接,然后将读写的I/O事件注册到另外的I/O线程池中,进行单独处理。


这里重点说说主从reactor模型,它接收客户端新连接的也是一个I/O线程组,可以多个线程去接收客户端的链接,然后将新连接交给另外的I/O线程组去处理读写消息的逻辑。


其中,主从模式中的主,指的是每个I/O线程单独监听一个服务端口,是N对N的关系,绝对不能理解为是多个I/O线程同时监听一个服务端口


END


点亮在看,你最好看

~

阅读原文,获得更多精彩内容

以上是关于Reactor主从模型你理解对了么?的主要内容,如果未能解决你的问题,请参考以下文章

Netty 4.x学习笔记——线程模型

reactor模式---事件触发模型

6.netty线程模型-Reactor

Java NIO Reactor网络编程模型的深度理解

五分钟快速理解 Reactor 模型

手绘模型图带你认识Kafka服务端网络模型