Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >netty系列之:EventLoop,EventLoopGroup和netty的默认实现

netty系列之:EventLoop,EventLoopGroup和netty的默认实现

原创
作者头像
程序那些事
发布于 2022-03-07 13:12:51
发布于 2022-03-07 13:12:51
92900
代码可运行
举报
文章被收录于专栏:程序那些事程序那些事
运行总次数:0
代码可运行

简介

在netty中不管是服务器端的ServerBootstrap还是客户端的Bootstrap,在创建的时候都需要在group方法中传入一个EventLoopGroup参数,用来处理所有的ServerChannel和Channel中所有的IO操作和event。

可能有的小伙伴还稍微看了一下netty的源码,可能会发现还有一个和EventLoopGroup非常类似的类叫做EventLoop。那么EventLoopGroup和EventLoop有什么关系呢?他们的底层和channel的交互关系是怎么样的呢?一起来看看吧。

EventLoopGroup和EventLoop

EventLoopGroup继承自EventExecutorGroup:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface EventLoopGroup extends EventExecutorGroup 

在前面的文章中我们讲过,EventExecutorGroup中有一个next方法可以返回对应的EventExecutor,这个方法在EventLoopGroup中进行了重写:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    EventLoop next();

next方法返回的不再是一个EventExecutor,而是一个EventLoop。

事实上,EventLoop和EventLoopGroup的关系与EventExecutor和EventExecutorGroup的关系有些类似,EventLoop也是继承自EventLoopGroup,EventLoopGroup是EventLoop的集合。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface EventLoop extends OrderedEventExecutor, EventLoopGroup 

在EventLoopGroup中,除了重写的next方法之外,还添加了channel的注册方法register,用于将channel和注册到EventLoop中,从而实现channel和EventLoop的绑定。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ChannelFuture register(Channel channel);

在EventLoop中,自多添加了一个parent方法,用来表示EventLoop和EventLoopGroup的关联关系:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
EventLoopGroup parent();

EventLoopGroup在netty中的默认实现

EventLoopGroup在netty中的默认实现叫做DefaultEventLoopGroup,先来看一下它的继承关系:

如果看了之前我讲解的关于EventExecutorGroup的朋友可以看出来,DefaultEventLoopGroup和DefaultEventExecutorGroup的继承关系是很类似的,DefaultEventLoopGroup继承自MultithreadEventLoopGroup,而MultithreadEventLoopGroup又继承自MultithreadEventExecutorGroup并且实现了EventLoopGroup接口:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup 

MultithreadEventLoopGroup是用多线程来处理Event Loop。

在MultithreadEventLoopGroup中定义了一个DEFAULT_EVENT_LOOP_THREADS来存储默认的处理Event Loop线程的个数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
                "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));

对于EventLoopGroup中新加的几个register方法,MultithreadEventLoopGroup都是调用对应的next方法来实现的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public ChannelFuture register(Channel channel) {
        return next().register(channel);
    }

这里的next()方法的实现实际上调用的是父类的next方法,也就是MultithreadEventExecutorGroup中的next方法,来选择Group管理的一个EventLoop:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public EventLoop next() {
        return (EventLoop) super.next();
    }

对于DefaultEventLoopGroup来说,它继承自MultithreadEventLoopGroup,实现了一个newChild方法,用来将传入的executor封装成为EventLoop:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    protected EventLoop newChild(Executor executor, Object... args) throws Exception {
        return new DefaultEventLoop(this, executor);
    }

EventLoop在netty中的默认实现

EventLoop在netty中的默认实现叫做DefaultEventLoop,先来看下它的继承关系:

DefaultEventLoop继承自SingleThreadEventLoop,而SingleThreadEventLoop又继承自SingleThreadEventExecutor并且实现了EventLoop接口。

先来看下SingleThreadEventLoop的实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop 

SingleThreadEventLoop使用单一线程来执行提交的任务。它和SingleThreadEventExecutor相比有什么变化呢?

首先 提供了一个tailTasks用来存储pending的tasks:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private final Queue<Runnable> tailTasks;

这个tailTasks会被用在任务个数的判断和操作上:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    final boolean removeAfterEventLoopIterationTask(Runnable task) {
        return tailTasks.remove(ObjectUtil.checkNotNull(task, "task"));
    }

    protected boolean hasTasks() {
        return super.hasTasks() || !tailTasks.isEmpty();
    }

    public int pendingTasks() {
        return super.pendingTasks() + tailTasks.size();
    }

SingleThreadEventLoop中对register方法的实现最终调用的是注册的channel中unsafe的register方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
channel.unsafe().register(this, promise);

再来看一下DefaultEventLoop,DefaultEventLoop继承自SingleThreadEventLoop:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DefaultEventLoop extends SingleThreadEventLoop 

除了构造函数之外,DefaultEventLoop实现了一个run方法,用来具体任务的执行逻辑:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    protected void run() {
        for (;;) {
            Runnable task = takeTask();
            if (task != null) {
                task.run();
                updateLastExecutionTime();
            }

            if (confirmShutdown()) {
                break;
            }
        }
    }

如果对比可以发现,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/

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
netty案例,netty4.1源码分析篇一《NioEventLoopGroup源码分析》
本章节我们从一个基础构建的基础NettyServer来分析NioEventLoopGroup源码,其中包括了;EventLoopGroup事件循环组、NioEventLoopGroup异步事件循环组、MultithreadEventLoopGroup多线程事件循环组等。
小傅哥
2020/07/14
4890
netty案例,netty4.1源码分析篇一《NioEventLoopGroup源码分析》
Netty(八)之Netty服务端启动流程
参数多传了一个DefaultSelectStrategyFactory.INSTANCE ,一个工厂类
CBeann
2023/12/25
3090
Netty(八)之Netty服务端启动流程
netty系列之:EventExecutor,EventExecutorGroup和netty中的实现
netty作为一个异步NIO框架,多线程肯定是它的基础,但是对于netty的实际使用者来说,一般是不需要接触到多线程的,我们只需要按照netty框架规定的流程走下去,自定义handler来处理对应的消息即可。
程序那些事
2022/03/04
8650
netty系列之:EventExecutor,EventExecutorGroup和netty中的实现
netty源码分析之EventLoop中的线程FastThreadLocalThread和队列
它继承自SingleThreadEventLoop,它的超类是SingleThreadEventExecutor。而在下面你会发现NioEventLoopGroup中维护着多个SingleThreadEventExecutor。先来看下NioEventLoop和SingleThreadEventLoop、SingleThreadEventExecutor的代码。
山行AI
2020/04/07
1.3K1
netty源码分析之EventLoop中的线程FastThreadLocalThread和队列
Netty Review - NioEventLoopGroup源码解析
这段代码是在使用Netty框架时常见的用法,用于创建两个不同的EventLoopGroup实例,一个用于处理连接请求(通常称为bossGroup),另一个用于处理连接后的数据流(通常称为workerGroup)。
小小工匠
2024/05/26
1370
Netty Review - NioEventLoopGroup源码解析
第二十节 netty源码分析之 reactor中的EventLoop01
EventLoopGroup (如果使用到的是 NIO, 那么通常是 NioEventLoopGroup), 那么这个 NioEventLoopGroup 在 Netty 中到底扮演着什么角色呢?
用户1418372
2019/03/11
3630
第二十节  netty源码分析之 reactor中的EventLoop01
敖丙肝了一个月的Netty知识点
高能预警,本文是我一个月前就开始写的,所以内容会非常长,当然也非常硬核,dubbo源码系列结束之后我就想着写一下netty系列的,但是netty的源码概念又非常多,所以才写到了现在。
敖丙
2021/01/08
1.1K0
敖丙肝了一个月的Netty知识点
Netty:server启动流程解析
1. reactor的线程模型; 2. 安全有效的nio非阻塞io模型应用; 3. pipeline流水线式的灵活处理过程; 4. channelHandler的灵活实现; 5. 提供许多开箱即用的处理器和编解码器;
烂猪皮
2020/12/31
1.1K0
Netty:server启动流程解析
netty源码分析二之EventLoopGroup初始化
这里的DEFAULTEVENTLOOP_THREADS的默认值是cpu核数乘以2:
山行AI
2019/10/24
7060
Netty 源码解析 ——— 服务端启动流程 (上)
本文是Netty文集中“Netty 源码解析”系列的文章。主要对Netty的重要流程以及类进行源码解析,以使得我们更好的去使用Netty。Netty是一个非常优秀的网络框架,对其源码解读的过程也是不断
tomas家的小拨浪鼓
2018/06/27
9200
netty系列之:NIO和netty详解
netty为什么快呢?这是因为netty底层使用了JAVA的NIO技术,并在其基础上进行了性能的优化,虽然netty不是单纯的JAVA nio,但是netty的底层还是基于的是nio技术。
程序那些事
2022/03/09
6460
Netty组件之Channel注册
本文将分析EventLoopGroup初始化、EventLoop的选择策略以及Channel是如何通过EventLoop注册到Selector上的。
瓜农老梁
2020/07/22
5370
NioEventLoopGroup 源码分析
NioEventLoopGroup 源码分析 1. 在阅读源码时做了一定的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限。为了方便 IDE 查看、跟踪、调试 代码,所以在 github 上提供 netty 的源码、详细的注释及测试用例。欢迎大家 star、fork ! 2. 由于个人水平有限,对源码的分析理解可能存在偏差或不透彻的地方还请大家在评论区指出,谢谢!    从今天开始,就准备进军 ne tty 了,主要的想法是看看 netty4 中一些比较重要的实现,也就是能经常出现在我
lwen
2018/04/17
6400
NioEventLoopGroup源码解析
我们前面说到过,NioEventLoopGroup我们可以近乎把它看作是一个线程池,该线程池会执行一个一个的任务,我们常用的NioEventLoopGroup大概有两种,NioEventLoopGroup(int nThreads),NioEventLoopGroup(),即一个是指定线程数量的,一个是默认指定线程数量的!这里我们以无参构造为入口进行分析!
止术
2021/07/16
7480
NioEventLoopGroup源码解析
Netty学习二
前面我们已经了解了官方的Netty的example,知道要编写一个一个聊天demo或者一个简单的rpc,或者应答模式的demo,在Netty中通常需要写服务端和客户端的引导,而引导是启动服务用的,而服务端和客户端的Handler则是用于处理具体的业务逻辑。这个通常在RPC框架中比如Dubbo,通常会在服务进行暴露或者进行引用的时候,需要调用Netty服务进行启动,然后进行暴露或者调用的,此时采用协议适配的时候,采用适配器模式,而我们知道生产者端最重要的方法就是doBind方法,而在消费者端最重要的方法是doConnect方法。而在RocketMQ中,我们也可以看到服务端和消费端中producer.start()和consumer.start()的时候都会调用Netty进行启动操作,也有类似的操作。
路行的亚洲
2020/07/16
4620
【Netty】「萌新入门」(二)剖析 EventLoop
本篇博文是《从0到1学习 Netty》中入门系列的第二篇博文,主要内容是介绍 Netty 中 EventLoop 的使用,优化及源码解析,往期系列文章请访问博主的 Netty 专栏,博文中的所有代码全部收集在博主的 GitHub 仓库中;
sidiot
2023/08/30
4910
【Netty】「萌新入门」(二)剖析 EventLoop
聊聊 Netty 那些事儿之 Reactor 在 Netty 中的实现(创建篇)
在上篇文章《聊聊Netty那些事儿之从内核角度看IO模型》中我们花了大量的篇幅来从内核角度详细讲述了五种IO模型的演进过程以及ReactorIO线程模型的底层基石IO多路复用技术在内核中的实现原理。
bin的技术小屋
2022/07/20
1.1K1
聊聊 Netty 那些事儿之 Reactor 在 Netty 中的实现(创建篇)
【Netty之旅四】你一定看得懂的Netty客户端启动源码分析!
源码系列的文章依旧还是遵循大白话+画图的风格来讲解,本文Netty源码及以后的文章版本都基于:4.1.22.Final
一枝花算不算浪漫
2020/09/24
6510
【Netty之旅四】你一定看得懂的Netty客户端启动源码分析!
深入Netty事件流程分析(上)
前面我们已经深入分析Netty中的核心组件,接下来我们开始来深入理解Netty各个组件处理事件的运作流程,通过事件流程的分析,我们可以思考Netty框架是如何设计组件之间的协作来配合完成基于Reactor模式且具备可伸缩性的Web服务,由于Netty事件流程比较多且杂,上篇主要分析事件轮询器初始化,启动类初始化组件以及服务端的端口绑定事件.
小坤探游架构笔记
2020/05/07
1.2K0
reactor-netty中TcpClient的create过程
本文主要研究一下reactor-netty中TcpClient的create的过程
code4it
2018/09/17
1.9K0
相关推荐
netty案例,netty4.1源码分析篇一《NioEventLoopGroup源码分析》
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验