一起学netty(8)EventLoop和EventLoopGroup理解
之前的文章中提到过,单线程的nio模型任然有一定缺点。在上一节《一起学netty(7)netty的线程模型》中也提到,netty的出现,封装了nio复杂的代码,并且介入多线程来处理事件,最大限度的提高了效率。
本文我们继续探究EventLoop、EventLoopGroup的概念以及和nio代码之间的关系。
EventLoop
EventLoop是一个事件循环对象,本质上是一个单线程的执行器(其中维护了一个Selector多路复用器)用于处理io事件。两外它实现了ScheduledExecutorService接口,所以它包含有关线程池的方法。
EventLoopGroup
EventLoopGroup是一个事件循环组,可以看作一个线程池,它包含一组EventLoop一组事件循环对象。
netty模型图
在netty的入门代码中,首先就定义了两个事件循环组。
//创建两个事件循环组bossGroup和workGroup,含有的子线程NioEventLoop的个数默认为cpu核心数的两倍。
//bossGroup只处理连接请求,workGroup处理客户端消息收发的业务。
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workGroup = new NioEventLoopGroup(8);
//服务端对象
ServerBootstrap serverBootstrap = new ServerBootstrap();
//绑定线程组
serverBootstrap.group(bossGroup,workGroup)
//使用NioServerSocketChannel作为服务器的通道实现
.channel(NioServerSocketChannel.class)
...
其中bossGroup就对应了上图的Boss Group,workGroup 就对应了上图的Work Group。
在netty的线程模型中采用的是主从多线程模型,上图中Boss Group上有一个EventLoop,该事件循环对象上绑定了一个多路复用器Selector,专门用于处理客户端的连接事件。当连接建立完成后,会产生一个SocketChannel,然后该SocketChannel会被注册到Work Group上的其中一个EventLoop事件循环对象上,该事件循环对象也会绑定一个Selector多路复用器,专门用于处理客户端的数据收发等事件。其中每个事件循环对象都可能会绑定多个SocketChannel。那么这样的效率就会比较高。
对比nio程序如下
一般客户端连接事件并发量较少,处理起来交简单,所以一般用一个或很少几个线程就能解决。
而客户端数据收发比较频繁,所以一般需要的线程数也就是EventLoop比较多一点。