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

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

目录



简介


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


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


EventLoopGroup和EventLoop


EventLoopGroup继承自EventExecutorGroup:


public interface EventLoopGroup extends EventExecutorGroup


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


EventLoop next();


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


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


public interface EventLoop extends OrderedEventExecutor, EventLoopGroup


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


ChannelFuture register(Channel channel);


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


EventLoopGroup parent();


EventLoopGroup在netty中的默认实现


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


image.png


如果看了之前我讲解的关于EventExecutorGroup的朋友可以看出来,DefaultEventLoopGroup和DefaultEventExecutorGroup的继承关系是很类似的,

DefaultEventLoopGroup继承自MultithreadEventLoopGroup,而MultithreadEventLoopGroup又继承自MultithreadEventExecutorGroup并且实现了EventLoopGroup接口:


public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup


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


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


DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
                "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));


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


public ChannelFuture register(Channel channel) {
        return next().register(channel);
    }


这里的next()方法的实现实际上调用的是父类的next方法,也就是

MultithreadEventExecutorGroup中的next方法,来选择Group管理的一个EventLoop:


public EventLoop next() {
        return (EventLoop) super.next();
    }


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


protected EventLoop newChild(Executor executor, Object... args) throws Exception {
        return new DefaultEventLoop(this, executor);
    }


EventLoop在netty中的默认实现


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


image.png


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


先来看下SingleThreadEventLoop的实现:


public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop


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


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


private final Queue<Runnable> tailTasks;


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


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方法:


channel.unsafe().register(this, promise);


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


public class DefaultEventLoop extends SingleThreadEventLoop


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


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的详细介绍,我们会在后一章中详细讲解,敬请期待。


相关文章
|
1月前
|
监控 前端开发 Java
事件驱动的奇迹:深入理解Netty中的EventLoop
事件驱动的奇迹:深入理解Netty中的EventLoop
58 0
|
1月前
|
安全 Java
【Netty 网络通信】EventLoop 事件循环对象 解析
【1月更文挑战第9天】【Netty 网络通信】EventLoop 事件循环对象 解析
|
11月前
|
缓存 Java 测试技术
Netty实战(七)EventLoop和线程模型
简单地说,线程模型指定了操作系统、编程语言、框架或者应用程序的上下文中的线程管理的关键方面。
114 0
|
11月前
|
监控 安全 Java
Netty之EventLoop 解读
Netty之EventLoop 解读
|
安全
关于netty的EventLoop
关于netty的EventLoop
关于netty的EventLoop
|
Java API 调度
Netty组件EventLoopGroup和EventLoop源码分析
Netty组件EventLoopGroup和EventLoop源码分析
58 0
|
安全 Java
Netty「源码阅读」之 EventLoop 简单介绍到源码分析
Netty「源码阅读」之 EventLoop 简单介绍到源码分析
176 0
|
缓存 Java 测试技术
【Netty】EventLoop和线程模型
在学习了ChannelHandler和ChannelPipeline的有关细节后,接着学习Netty的EventLoop和线程模型。
176 0
【Netty】EventLoop和线程模型
|
存储 缓存 NoSQL
跟着源码学IM(十一):一套基于Netty的分布式高可用IM详细设计与实现(有源码)
本文将要分享的是如何从零实现一套基于Netty框架的分布式高可用IM系统,它将支持长连接网关管理、单聊、群聊、聊天记录查询、离线消息存储、消息推送、心跳、分布式唯一ID、红包、消息同步等功能,并且还支持集群部署。
13283 1
|
7天前
|
机器学习/深度学习 缓存 算法
netty源码解解析(4.0)-25 ByteBuf内存池:PoolArena-PoolChunk
netty源码解解析(4.0)-25 ByteBuf内存池:PoolArena-PoolChunk