Netty Reactor模式
Netty对三种IO模式的支持:
BIO-> OIO (Deprecated) |
NIO |
AIO (Removed) |
||
Common |
Linux |
macOS/BSD |
||
ThreadPerChannelEventLoopGroup |
NioEventLoopGroup |
EpollEventLoopGroup |
KQueueEventLoopGroup |
AioEventLoopGroup |
ThreadPerChannelEventLoop |
NioEventLoop |
EpollEventLoop | KQueueEventLoop |
AioEventLoop |
OioServerSocketChannel |
NioServerSocketChannel |
EpollServerSocketChannel | KQueueServerSocketChannel |
AioServerSocketChannel |
OioSocketChannel |
NioSocketChannel |
EpollSocketChannel |
KQueueSocketChannel |
AioSocketChannel |
三种IO模式及对应的开发模式:
BIO | NIO | AIO |
Thread-Per-Connection | Reactor | Proactor |
Thread-Per-Connection模式:
对于每一个连接都有一个单独的线程,读、解码、运算、编码、响应操作都是在一个线程上。
其中读和响应都是阻塞操作。
Reactor
Reactor是服务端在网络编程时的一个编程模式,主要由一个基于Selector(底层是select/poll/epoll)的死循环线程,也称为Reactor线程。将IO操作抽象成不同的事件,每个事件都配置对应的回调函数,由Selector监听连接上事件的发生,再进行分发调用相应的回调函数进行事件的处理。
Reactor是一种开发模式,模式的核心流程:
注册感兴趣的事件——>扫描是否有感兴趣的事件发生——>事件发生后做出相应的处理。
不同Channel感兴趣(监听)的事件:
Client/Server | SocketChannel/ServerSocketChannel | OP_ACCEPT(接受连接) | OP_CONNECT(连接) | OP_WRITE(读) | OP_READ(写) |
client | SocketChannel | Y | Y | Y | |
server | ServerSocketChannel | Y | |||
server | SocketChannel | Y | Y |
三种Reactor模式:
①、Reactor单线程:
Reactor的单线程模式的单线程主要是针对于I/O操作而言,也就是所以的I/O的accept()、read()、write()以及connect()操作都在一个线程上完成的
②、非主从 Reactor 多线程模式:
与单线程模式不同的是,添加了一个worker 线程池,并将非I/O操作从Reactor线程中移出转交给worker 线程池(Thread Pool)来执行。这样能够提高Reactor线程的I/O响应,不至于因为一些耗时的业务逻辑而延迟对后面I/O请求的处理
虽然非I/O操作交给了worker 线程池来处理,但是所有的I/O操作依然由Reactor单线程执行,在高负载、高并发或大数据量的应用场景,依然较容易成为瓶颈
③、主从Reactor多线程模式
对于多个CPU的机器,为充分利用系统资源,将Reactor拆分为两部分:mainReactor和subReactor
mainReactor负责监听server socket,用来处理网络新连接的建立,将建立的socketChannel指定注册给subReactor,通常一个线程就可以处理
subReactor维护自己的selector, 基于mainReactor 注册的socketChannel多路分离I/O读写事件,读写网络数据,通常使用多线程
对非I/O的操作,依然转交给worker 线程池(Thread Pool)执行
此种模型中,每个模块的工作更加专一,耦合度更低,性能和稳定性也大量的提升,支持的可并发客户端数量可达到上百万级别。关于此种模型的应用,目前有很多优秀的框架已经在应用了,比如mina和netty 等。Reactor模式-多线程模式下去掉工作者线程池(Thread Pool),则是Netty中NIO的默认模式
mainReactor对应Netty中配置的BossGroup线程组,主要负责接受客户端连接的建立。一般只暴露一个服务端口,BossGroup线程组一般一个线程工作即可
subReactor对应Netty中配置的WorkerGroup线程组,BossGroup线程组接受并建立完客户端的连接后,将网络socket转交给WorkerGroup线程组,然后在WorkerGroup线程组内选择一个线程,进行I/O的处理。WorkerGroup线程组主要处理I/O,一般设置2*CPU核数个线程
如何在Netty中使用Reactor三种模式:
Reactor 单线程模式 |
EventLoopGroup eventGroup = new NioEventLoopGroup(1); ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(eventGroup); |
非主从 Reactor 多线程模式 |
EventLoopGroup eventGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(eventGroup); |
主从 Reactor 多线程模式 |
EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup); |
END.