netty线程模型
目前存在的线程模型有
传统阻塞I/O服务模型,采用阻塞IO获取输入的数据,每个连接都需要独立的线程操作,无法实现高并发
Reactor模式
- 基于IO复用模型:多个连接共用一个阻塞对象,应用程序只需在一个阻塞对象等待,无需阻塞等待多个连接,当某个连接有新的数据可以处理时,操作系统通知应用程序,线程开始进行业务处理
- 基于线程池复用线程资源:不必再为每个连接创建线程,将连接完成后的业务处理任务分配给线程进行处理,一个线程可以处理多个连接的业务
根据Reactor的数量和处理资源线程的数量不同,有三种实现
单Reactor单线程
所有IO操作都由一个线程完成,即多路复用、事件分发和处理都是在一个Reactor线程上完成的,既要接收客户端的连接请求,向服务器发起连接,又要读取请求或响应消息
- 优点:模型简单,没有多线程问题,全都在一个线程完成
- 缺点:单线程无法发挥多核CPU的性能,handler在处理某个连接上的业务时,无法处理其他连接的事件
单Reactor多线程
一个NIO线程只负责监听服务端,接收客户端的TCP连接请求;一个NIO线程池负责网络IO的操作,即消息的读取、编解码和响应消息
- 优点:可以充分利用多核CPU
- 缺点:多线程数据共享比较复杂
主从Reactor多线程
Acceptor线程用于绑定监听端口,接收客户端连接,将SocketChannel从主线程的Reactor线程的多路复用器上移除,重新注册到Sub线程池的线程上,用于处理IO的读写操作
- 优点:父子线程数据交互简单职责明确,父线程只需要接收新连接,子线程完成后续的业务处理
- 缺点:编程复杂度高
Netty线程模型是基于主从Reactor多线程模型进行了一定的改进,内部实现了两组线程池,boss线程池和work线程池,其中boss线程池的线程负责处理请求的accept事件,当接收到accept事件的请求时,把对应的socket封装到一个NioSocketChannel中,并交给work线程池,work线程池负责请求的read和write事件,由对应的Handler处理
工作原理
- netty中有两组线程池NioEventLoopGroup(事件循环组,这个组中包含有多个事件循环,每一个事件循环都是NioEventLoop,NioEventLoop是一个不断循环的执行处理线程,每个NioEventLoop都有一个selector,用于监听绑定在其上的socket的网络通讯),BossGroup 专门负责接收客户端的连接,WorkerGroup 专门负责网络的读写,在每个NioEventLoopGroup中可以有多个线程,即可以有多个NioEventLoop
- BossGroup处理接收事件
- 轮询accept事件
- 处理accept事件,与client建立连接,生成NioSocketChannel,并将其注册到某个worker中NioEventLoop的selector
- 处理任务队列的任务,即runAllTasks
- WorkerGroup进行业务处理
- 轮询read,write事件
- 处理read,write事件
- 处理任务队列的任务,即runAllTasks