netty 系列之:EventLoop,EventLoopGroup 和 netty 的默认实现
简介
在 netty 中不管是服务器端的 ServerBootstrap 还是客户端的 Bootstrap,在创建的时候都需要在 group 方法中传入一个 EventLoopGroup 参数,用来处理所有的 ServerChannel 和 Channel 中所有的 IO 操作和 event。
可能有的小伙伴还稍微看了一下 netty 的源码,可能会发现还有一个和 EventLoopGroup 非常类似的类叫做 EventLoop。那么 EventLoopGroup 和 EventLoop 有什么关系呢?他们的底层和 channel 的交互关系是怎么样的呢?一起来看看吧。
EventLoopGroup 和 EventLoop
EventLoopGroup 继承自 EventExecutorGroup:
在前面的文章中我们讲过,EventExecutorGroup 中有一个 next 方法可以返回对应的 EventExecutor,这个方法在 EventLoopGroup 中进行了重写:
next 方法返回的不再是一个 EventExecutor,而是一个 EventLoop。
事实上,EventLoop 和 EventLoopGroup 的关系与 EventExecutor 和 EventExecutorGroup 的关系有些类似,EventLoop 也是继承自 EventLoopGroup,EventLoopGroup 是 EventLoop 的集合。
在 EventLoopGroup 中,除了重写的 next 方法之外,还添加了 channel 的注册方法 register,用于将 channel 和注册到 EventLoop 中,从而实现 channel 和 EventLoop 的绑定。
在 EventLoop 中,自多添加了一个 parent 方法,用来表示 EventLoop 和 EventLoopGroup 的关联关系:
EventLoopGroup 在 netty 中的默认实现
EventLoopGroup 在 netty 中的默认实现叫做 DefaultEventLoopGroup,先来看一下它的继承关系:
<img src="https://img-blog.csdnimg.cn/119283e9b8d04854940abc0fc159c604.png" style="zoom:67%;" />
如果看了之前我讲解的关于 EventExecutorGroup 的朋友可以看出来,DefaultEventLoopGroup 和 DefaultEventExecutorGroup 的继承关系是很类似的,DefaultEventLoopGroup 继承自 MultithreadEventLoopGroup,而 MultithreadEventLoopGroup 又继承自 MultithreadEventExecutorGroup 并且实现了 EventLoopGroup 接口:
MultithreadEventLoopGroup 是用多线程来处理 Event Loop。
在 MultithreadEventLoopGroup 中定义了一个 DEFAULT_EVENT_LOOP_THREADS 来存储默认的处理 Event Loop 线程的个数:
对于 EventLoopGroup 中新加的几个 register 方法,MultithreadEventLoopGroup 都是调用对应的 next 方法来实现的:
这里的 next()方法的实现实际上调用的是父类的 next 方法,也就是 MultithreadEventExecutorGroup 中的 next 方法,来选择 Group 管理的一个 EventLoop:
对于 DefaultEventLoopGroup 来说,它继承自 MultithreadEventLoopGroup,实现了一个 newChild 方法,用来将传入的 executor 封装成为 EventLoop:
EventLoop 在 netty 中的默认实现
EventLoop 在 netty 中的默认实现叫做 DefaultEventLoop,先来看下它的继承关系:
<img src="https://img-blog.csdnimg.cn/9c642b58f6c248f9bddfbb71799549f9.png" style="zoom:67%;" />
DefaultEventLoop 继承自 SingleThreadEventLoop,而 SingleThreadEventLoop 又继承自 SingleThreadEventExecutor 并且实现了 EventLoop 接口。
先来看下 SingleThreadEventLoop 的实现:
SingleThreadEventLoop 使用单一线程来执行提交的任务。它和 SingleThreadEventExecutor 相比有什么变化呢?
首先 提供了一个 tailTasks 用来存储 pending 的 tasks:
这个 tailTasks 会被用在任务个数的判断和操作上:
SingleThreadEventLoop 中对 register 方法的实现最终调用的是注册的 channel 中 unsafe 的 register 方法:
再来看一下 DefaultEventLoop,DefaultEventLoop 继承自 SingleThreadEventLoop:
除了构造函数之外,DefaultEventLoop 实现了一个 run 方法,用来具体任务的执行逻辑:
如果对比可以发现,DefaultEventLoop 和 DefaultEventExecutor 中 run 方法的实现是一样的。
总结
本文介绍了 netty 中 EventLoop 和 EventLoopGroup 的默认实现:DefaultEventLoop 和 DefaultEventLoopGroup,但是不知道小伙伴们有没有发现,即使在最简单的 netty 应用中也很少看到这两个默认的 EventLoop。最常用的反而是 NioEventLoopGroup 和 NioEventLoop,这是因为 DefaultEventLoop 和 DefaultEventLoopGroup 只是使用了多线程技术,一个线程代表一个 EventLoop,在 EventLoop 过多的情况下可能会造成线程和性能的浪费,所以在 NioEventLoopGroup 和 NioEventLoop 使用了 NIO 技术,通过使用 channel、selector 等 NIO 技术提升了 EventLoop 的效率。关于 NioEventLoopGroup 和 NioEventLoop 的详细介绍,我们会在后一章中详细讲解,敬请期待。
本文已收录于 http://www.flydean.com/05-1-netty-eventloop-eventloopgroup/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
版权声明: 本文为 InfoQ 作者【程序那些事】的原创文章。
原文链接:【http://xie.infoq.cn/article/111d316ddbddd3ba6f9a80c72】。文章转载请联系作者。
评论