Reactor的NIO线程模型
1.Reactor单线程模型
传统的javaNIO通信的线程模型。该线程模型仅有一个I/O线程处理所有的I/O操作,如下图:
所有的客户端都连接到一个I/O线程负责的Acceptor上,连接成功后,由Reactor里的Dispatch将接收的ByteBuffer分发到指定的Handler上处理,进行解码,业务处理,编码及发送给客户端等过程。整个过程I/O线程都是异步非阻塞方式实现。
I/O线程完成的工作:
1)服务端NIO线程用于监听客户端连接
2)客户端NIO线程用于向服务器端发送连接请求
3)客户端和服务端的读写操作
不足:
1)如果客户端同时有成百上千的请求,会导致I/O线程不停的工作,CPU利用率负荷超载,同时造成很多客户端超时得不到响应
2)一旦I/O线程出现异常,可能会导致所有客户端掉线,造成系统单点故障
2.多线程的Reactor模型
多线程模型采用1个线程接收客户端请求,同时使用1个线程池处理读写等操作。模型如下:
其中Acceptor单线程用于监听及接收client的连接请求,连接成功后会将这些连接注册到WorkThreadPool(工作线程池)的其中一个线程上,由工作线程池分出1个工作线程用于和该client的读写、编码、解码操作。一个client只能和一个工作线程对应,不能注册到多个工作线程,防止出现并发操作问题。
WorkThreadPool由一个任务队列和N个线程组成,client连接成功后的读写请求都会放到任务队列中,工作线程池会从任务队列中获取任务、分配线程进行处理。
注意:这里的工作线程并不是业务处理线程,工作线程只是负责业务线程处理前或者业务线程处理后的读写和编解码操作。比如解码成功后获取对应的消息内容后,对这些消息的处理是由单独的业务线程处理的,当然业务线程一般也是有自己的线程池。
不足:单独的Acceptor线程会成为系统的瓶颈,一旦出现问题,后面的工作线程池也无法工作。
3.主从Reactor模型
该模型是的Acceptor由一个线程池MainReactorThreadPool负责监听和接收client的连接、认证等,同时由另一个SubReactorThreadPool线程池负责读写、编码等工作。模型如下:
该模型可以有效解决Acceptor单线程瓶颈问题,同时能提高客户端并发能力,稳定性和处理效率高。
Netty支持上面三种不同的线程模型,针对不同的业务需求可以设置不同的启动参数,选择对应的线程模型,不过netty官网推荐使用第三种主从模式。