`
Tiger_WILL
  • 浏览: 8579 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Netty4之EventLoop浅析

阅读更多
EventLoop

EventLoop继承自EventExecutorEventLoopGroup。从这点可以看出EventLoop首先是一个Executor,任务执行器。
再者它本身是一个环,能够负载均衡执行压力。可以说EventLoop是Netty4的一个核心,整个Netty4的运转都是围绕着它。

一、认识EventLoop有哪些方法(下面列举的是一些比较典型的)
 EventLoop next()
	Future<?> submit(Runnable task)
	ChannelFuture register(Channel channel)
	ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
	Future<?> shutdownGracefully()

从这些方法,我们可以清晰的认识到EventLoop可以实现以下功能:
引用
1. 执行任务(IO/非IO任务)
2. 将Channel绑定到EventLoop上
3. 执行定时任务
4. 关闭任务


二、SingleThreadEventLoop & NioEventLoop - EventLoop的2个关键实现
SingleThreadEventLoop继承自SingleThreadEventExecutor这是一个标准的线程池的实现。和JDK中线程池的实现大同小异。主要的用处就是执行任务。
NioEventLoop继承自SingleThreadEventLoop也就是说他具备执行任务的能力。但是它更重要的是每个NioEventLoop里面包含一个Selector,也就是说
它具备网络处理能力。我们来看看它是如何工作的。

  • 启动时打开一个Selector
  • 从下面代码可以看到,Channel是这样绑定到NioEventLoop上的
  • protected void doRegister() throws Exception {
            boolean selected = false;
            for (;;) {
                try {
                    selectionKey = javaChannel().register(eventLoop().selector, 0, this);
                    return;
                } catch (CancelledKeyException e) {
                    if (!selected) {
                        // Force the Selector to select now as the "canceled" SelectionKey may still be
                        // cached and not removed because no Select.select(..) operation was called yet.
                        eventLoop().selectNow();
                        selected = true;
                    } else {
                        // We forced a select operation on the selector before but the SelectionKey is still cached
                        // for whatever reason. JDK bug ?
                        throw e;
                    }
                }
            }
        }
    

  • 从下面代码看到NioEventLoop做的事情就是处理各种NIO事件
  • @Override
        protected void run() {
            for (;;) {
                oldWakenUp = wakenUp.getAndSet(false);
                try {
                    if (hasTasks()) {
                        selectNow();
                    } else {
                        select();
                        if (wakenUp.get()) {
                            selector.wakeup();
                        }
                    }
    
                    cancelledKeys = 0;
    
                    final long ioStartTime = System.nanoTime();
                    needsToSelectAgain = false;
                    if (selectedKeys != null) {
                        processSelectedKeysOptimized(selectedKeys.flip());
                    } else {
                        processSelectedKeysPlain(selector.selectedKeys());
                    }
                    final long ioTime = System.nanoTime() - ioStartTime;
    
                    final int ioRatio = this.ioRatio;
                    runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
    
                    if (isShuttingDown()) {
                        closeAll();
                        if (confirmShutdown()) {
                            break;
                        }
                    }
                } catch (Throwable t) {
                    logger.warn("Unexpected exception in the selector loop.", t);
    
                    // Prevent possible consecutive immediate failures that lead to
                    // excessive CPU consumption.
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // Ignore.
                    }
                }
            }
        }
    

    private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
            final NioUnsafe unsafe = ch.unsafe();
            if (!k.isValid()) {
                // close the channel if the key is not valid anymore
                unsafe.close(unsafe.voidPromise());
                return;
            }
    
            try {
                int readyOps = k.readyOps();
                // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
                // to a spin loop
                if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
                    unsafe.read();
                    if (!ch.isOpen()) {
                        // Connection already closed - no need to handle write.
                        return;
                    }
                }
                if ((readyOps & SelectionKey.OP_WRITE) != 0) {
                    // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
                    ch.unsafe().forceFlush();
                }
                if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
                    // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
                    // See https://github.com/netty/netty/issues/924
                    int ops = k.interestOps();
                    ops &= ~SelectionKey.OP_CONNECT;
                    k.interestOps(ops);
    
                    unsafe.finishConnect();
                }
            } catch (CancelledKeyException e) {
                unsafe.close(unsafe.voidPromise());
            }
        }
    

  • Read操作最终会当作一个定时任务添加到NioEventLoop中被执行
  • public ChannelHandlerContext read() {
            final DefaultChannelHandlerContext next = findContextOutbound();
            EventExecutor executor = next.executor();
            if (executor.inEventLoop()) {
                next.invokeRead();
            } else {
                Runnable task = next.invokeReadTask;
                if (task == null) {
                    next.invokeReadTask = task = new Runnable() {
                        @Override
                        public void run() {
                            next.invokeRead();
                        }
                    };
                }
                executor.execute(task);
            }
    
            return this;
        }
    

  • 同样的Write操作会当作一个定时任务添加到NioEventLoop中被执行
  • private void write(Object msg, boolean flush, ChannelPromise promise) {
    
            DefaultChannelHandlerContext next = findContextOutbound();
            EventExecutor executor = next.executor();
            if (executor.inEventLoop()) {
                next.invokeWrite(msg, promise);
                if (flush) {
                    next.invokeFlush();
                }
            } else {
                int size = channel.estimatorHandle().size(msg);
                if (size > 0) {
                    ChannelOutboundBuffer buffer = channel.unsafe().outboundBuffer();
                    // Check for null as it may be set to null if the channel is closed already
                    if (buffer != null) {
                        buffer.incrementPendingOutboundBytes(size);
                    }
                }
                safeExecute(executor, WriteTask.newInstance(next, msg, size, flush, promise), promise, msg);
            }
        }
    

    总结:
    • NioEventLoop是Netty4最基础的一个东西
    • 在Netty4里面一切操作都是在NioEventLoop中被执行
    • NioEventLoop既能执行IO任务,也能执行非IO任务,它可以被Channel绑定,处理Channel中IO事物,也可以用来向它提交任务,当作一个任务管理器使用
    0
    0
    分享到:
    评论

    相关推荐

      Netty简介 Netty线程模型和EventLoop Codec编码与解码 ByteBuf容器

      EventLoopGroup是EventLoop的集合,通常有老板线程组和工作线程组之分,老板线程负责接受新的连接,然后分配给工作线程处理。 **ByteBuf容器** ByteBuf是Netty提供的字节缓冲区,它是Java NIO ByteBuffer的一个...

      guang19#framework-learning#Netty线程模型和EventLoop1

      Netty线程模型和EventLoop线程模型概述EventLoop事件循环任务调度JDK任务调度EventLoop任务调度线程管理线程分配非阻塞传输阻塞传输N

      Netty进阶之路-跟着案例学Netty

      本书首先会介绍Netty的基本概念,包括其非阻塞I/O模型、事件驱动架构以及Channel、EventLoop、Buffer等核心组件。接着,通过一系列逐步进阶的案例,如构建简单的Echo服务器、处理HTTP请求、实现WebSocket通信,读者...

      Netty实现原理浅析.pdf

      在Netty中,`NioEventLoopGroup`扮演着Reactor的角色,其中`NioEventLoop`实现了`EventLoop`接口,负责处理各种I/O事件。此外,`Bootstrap`和`ServerBootstrap`类分别用于客户端和服务端的启动配置。 #### 三、缓冲...

      netty4 api 中文

      这个“netty4 api 中文”压缩包包含的是Netty 4.1版本的中文API文档,对于Java开发者来说,是学习和使用Netty的重要参考资料。 Netty 的核心设计理念是基于Reactor模式,这种模式在处理并发I/O操作时能显著提高效率...

      netty4 中文学习资料

      6. **EventLoop 和 EventLoopGroup**: EventLoop 是执行事件处理的线程,EventLoopGroup 是 EventLoop 的集合。这种设计允许 Netty 在多线程环境下高效地处理并发连接。 7. **Future 和 Promise**: Netty 提供了 ...

      netty5 HTTP协议栈浅析与实践

      Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在本文中,我们将深入浅出地探讨 Netty 实现的 HTTP 协议栈,并通过实践来理解其工作原理。 首先,我们要...

      netty4 in action

      本书首先介绍了Netty的基本架构,包括它的Channel、EventLoop、Bootstrap、Pipeline等核心组件。Channel是Netty中处理网络通信的基本单元,可以理解为一个连接;EventLoop是负责处理I/O事件的线程,确保了高效的事件...

      netty4-netty5.rar

      ChannelHandlerAdapter 4.X版本和5.X版本的差别很大。ChannelRead是属于5.X版本的4.X版本没有这个方法,所以如果要用ChannelRead。可以更换5.X版本的Netty。

      使用Netty4实现多线程的消息分发

      1. **EventLoopGroup**:Netty 中的 EventLoopGroup 是一组事件循环(EventLoop)的集合,每个事件循环对应一个独立的工作线程。在服务器端,通常会创建两个 EventLoopGroup,一个用于接收客户端连接(BossGroup),...

      《Netty进阶之路 跟着案例学Netty》.rar

      Java进阶技术-netty进阶之路

      netty4 sources 源码

      这个“netty4 sources 源码”指的是Netty 4.x 版本的源代码,其中4.0.33.Final是特定的版本号。源码分析对于理解Netty的工作原理、优化性能以及定制化开发非常有帮助。 Netty 的核心特性包括: 1. **异步事件驱动*...

      transport-netty4-client-5.5.1-API文档-中英对照版.zip

      赠送jar包:transport-netty4-client-5.5.1.jar; 赠送原API文档:transport-netty4-client-5.5.1-javadoc.jar; 赠送源代码:transport-netty4-client-5.5.1-sources.jar; 赠送Maven依赖信息文件:transport-netty...

      netty+4G DTU

      4. **异常处理**:定义异常处理器,捕获并处理可能出现的网络异常,如连接断开、超时等。 5. **数据处理**:根据业务需求,解析接收到的数据并进行相应的业务逻辑处理,如存储数据、触发报警、执行远程控制等。 6....

      03-04-06-大名鼎鼎的EventLoop1

      【描述】:“第 5 章Netty 高性能之道第 6 章揭开 BootStrap 的神秘面纱第 7 章大名鼎鼎的 EventLoop第 8 章Netty 大动脉 Pipeline” 【标签】:“” 【部分内容】:“咕泡出品,必属精品 www.gupaoedu.com1第 3 ...

      《Netty进阶之路 跟着案例学Netty》_李林锋_

      Netty进阶之路 跟着案例学Netty 整本书无密码,Netty进阶之路 跟着案例学Netty

      Netty4.x源码分析详解

      4. **EventLoop**:探索事件循环的调度机制,如何平衡负载和处理并发请求。 5. **编码解码器**:如 LengthFieldBasedFrameDecoder 和 StringDecoder,它们是如何将原始字节流转换为应用程序可用的数据对象的。 6. **...

      netty4-demos

      这意味着在 Netty 中,I/O 操作不会阻塞线程,而是通过事件循环(EventLoop)和事件处理器(ChannelHandler)来处理。当 I/O 操作完成时,相应的事件会被触发,然后由事件处理器进行处理,这样极大地提高了系统性能...

      transport-netty4-client-6.3.0-API文档-中文版.zip

      赠送jar包:transport-netty4-client-6.3.0.jar; 赠送原API文档:transport-netty4-client-6.3.0-javadoc.jar; 赠送源代码:transport-netty4-client-6.3.0-sources.jar; 赠送Maven依赖信息文件:transport-netty...

      netty4与spring集成

      4. **ChannelHandler 配置**: ChannelHandler 是 Netty 中处理网络事件的核心组件。在 Spring 集成中,可以创建一个 ChannelHandlerContext 的工厂类,该工厂由 Spring 管理,并在需要时为每个新建的 Channel 提供 ...

    Global site tag (gtag.js) - Google Analytics