学一学Netty中的NioEventLoopGroup
- 一个Netty程序启动时,至少要指定一个EventLoopGroup
- 假如我们使用NIO,那我们通常使用NioEventLoopGroup
- 使用BIO,那我们可以初始化OioEventLoopGroup
官方DOC
- 上图时Netty(4.1.6)中EventLoopGroup的解释
- 在事件循环期间可对EventExecutorGroup进行Channel的注册,然后供后续使用
- 到这里有一个模糊的概念,EventLoopGroup可以对Channel进行注册
方法实现
- 通过其提供的接口方法可以发现EventLoopGroup定义了Channel的注册规范
EventLoopGroup结构图
父结构
- 这里发现它的顶层父类是Executor对象。我们知道Netty是基于Java实现的RPC框架
- 那么看到这里不难理解,EventLoopGroup其实是和线程相关的
- Netty本质又是Reactor模型的实现,那么EventLoopGroup和Reactor肯定是有关系的
EventLoopGroup与Reactor
- 还是熟悉的代码
EventLoopGroup workerGroup = new NioEventLookGroup();
Bootstrap boot = new Bootstrap();
boot.group(workerGroup);
-
这里初始化了一个NioEventLookGroup对象,那么先来看一下EventLoopGroup的子结构
-
通过其子结构类图可以发现一些端倪
SingleThreadEventLoop : 在一个线程中执行所有提交的任务
MultithreadEventLoopGroup : 多线程并发处理提交的任务
EmbeddedEventLoop : 用来测试
ThreadPerChannelEventLoop : 提供OIO的处理模式,每一个EventLoop对应一个线程对应一个Channel
通过NioEventLoopGroup窥视其冰山一角
- NioEventLoopGroup官方DOC
- 使用NIO模型,基于Channel选择了Selector选择器
- 初始化
- 未传入参数的话,使用默认线程数。并且在初始化过程中创建一个SelectorProvider对象,后续用来提供Selector
- 默认线程数:处理器数 * 2
Bootstrap—group方法
- 客户端实现
EventLoopGroup workerGroup = new NioEventLookGroup();
Bootstrap boot = new Bootstrap();
boot.group(workerGroup);
- 服务端实现
EventLoopGroup group = new NioEventLookGroup();
// 与客户端不同,服务端使用 ServerBootstrap
ServerBootstrap boot = new ServerBootstrap();
boot.group(group);
- 服务端group方法实现
- 这里我们可以发现,服务端的boss线程和worker线程实际上是同一个线程
- 到这里我们可以发现,当我们设置单线程的时候。
- NioEventLoopGroup线程池的数量只设置为1
- Netty中的Acceptor和后续所有的接收到的请求都是在一个线程中处理的
- 对应Reactor线程模型,就相当于Reactor的单线程模型
单线程模型
EventLoopGroup group = new NioEventLookGroup();
// 与客户端不同,服务端使用 ServerBootstrap
ServerBootstrap boot = new ServerBootstrap();
boot.group(group);
多线程模型
// 设置 n > 1的线程数,当然要合理,不能无限大
EventLoopGroup group = new NioEventLookGroup(n);
// 与客户端不同,服务端使用 ServerBootstrap
ServerBootstrap boot = new ServerBootstrap();
boot.group(group);
主从线程模型
EventLoopGroup boos = new NioEventLookGroup();
EventLoopGroup work = new NioEventLookGroup();
// 与客户端不同,服务端使用 ServerBootstrap
ServerBootstrap boot = new ServerBootstrap();
boot.group(boos, worker);
- 看代码,通过对parentGroup和childGroup进行不同的处理,确定其不同的工作职责
NioEventLoopGroup如何工作的
- 现在,对NioEventLoopGroup的作用以及原理有了一个基本的认识
- 那么当任务过来的时候是如何被执行的呢
NioEventLoopGroup的实例化
- 通过其实例化过程入手
- 调用到 其父类 MultithreadEventLoopGroup 的构造方法,进行线程相关参数的设置
-
调用到 MultithreadEventExecutorGroup 的 构造方法,重点看其中的 newChild 方法
- 根据线程数量做循环
- 根据线程数量做循环
-
又回调到 NioEventLoopGroup 的 newChild 方法
- 走到 NioEventLoop 的构造方法
- 走到这里看到了熟悉的方法openSelector()选择器出现了