1 NioEventLoop概述

Netty 源码阅读入门实战(四)-NioEventLoop
  • 总述


    Netty 源码阅读入门实战(四)-NioEventLoop

2 NioEventLoop创建概述

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

对应


Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

对应
Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

对应
Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

对应
Netty 源码阅读入门实战(四)-NioEventLoop

3 ThreadPerTaskThread

2 服务端Channel的创建

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

bind 对应样例的


Netty 源码阅读入门实战(四)-NioEventLoop
跟进调试

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
通过反射创建的 channel

看看 channelFactory


Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
  • 反射创建服务端 Channel


    Netty 源码阅读入门实战(四)-NioEventLoop

    首先


    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop
    创建完毕了

    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop
  • ANC


    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop

4 创建NioEventLoop线程

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

5 创建线程选择器

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
  • 先看看普通的


    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop
  • 再看幂2的


    Netty 源码阅读入门实战(四)-NioEventLoop

    Netty 源码阅读入门实战(四)-NioEventLoop
    循环取数组索引下标,& 比取模性能更高

6 NioEventLoop的启动

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

对应是


Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

对应是
Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

7 NioEventLoop执行概述

8 检测IO事件

Netty 源码阅读入门实战(四)-NioEventLoop
Netty 源码阅读入门实战(四)-NioEventLoop

对应的源码为


Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

对应的源码为


Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
执行至此,说明已进行了一次阻塞式的 select 操作

Netty 源码阅读入门实战(四)-NioEventLoop
产生空轮询的判断

Netty 源码阅读入门实战(四)-NioEventLoop
当空轮询次数大于阈值

Netty 源码阅读入门实战(四)-NioEventLoop
阈值定义

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
阈值

Netty 源码阅读入门实战(四)-NioEventLoop

避免空轮询的再次发生


Netty 源码阅读入门实战(四)-NioEventLoop
创建新选择器

Netty 源码阅读入门实战(四)-NioEventLoop
获取旧选择器的所有 key 值

Netty 源码阅读入门实战(四)-NioEventLoop
netty 包装的 channel

Netty 源码阅读入门实战(四)-NioEventLoop
将之前的 key 事件解除,并绑定新的选择器和对应的事件

Netty 源码阅读入门实战(四)-NioEventLoop
更新选择器的 key

Netty 源码阅读入门实战(四)-NioEventLoop
至此,解决了空轮bug

9 处理IO事件

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
原生JDK创建一个 selector

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
单线程处理,其实不需要两个数组,后续版本已经是一个数组

Netty 源码阅读入门实战(四)-NioEventLoop
只需关注

Netty 源码阅读入门实战(四)-NioEventLoop
根本不需要此三个方法

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
通过反射

Netty 源码阅读入门实战(四)-NioEventLoop
即此类

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
继续反射流程

Netty 源码阅读入门实战(四)-NioEventLoop
替换为优化后的 set 集合

一句话总结:用数组替换HashSet 的实现,做到 add 时间复杂度为O(1)


Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
 private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
        final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
        if (!k.isValid()) {
            final EventLoop eventLoop;
            try {
                eventLoop = ch.eventLoop();
            } catch (Throwable ignored) {
                // If the channel implementation throws an exception because there is no event loop, we ignore this
                // because we are only trying to determine if ch is registered to this event loop and thus has authority
                // to close ch.
                return;
            }
            // Only close ch if ch is still registerd to this EventLoop. ch could have deregistered from the event loop
            // and thus the SelectionKey could be cancelled as part of the deregistration process, but the channel is
            // still healthy and should not be closed.
            // See https://github.com/netty/netty/issues/5125
            if (eventLoop != this || eventLoop == null) {
                return;
            }
            // close the channel if the key is not valid anymore
            unsafe.close(unsafe.voidPromise());
            return;
        }

        try {
            int readyOps = k.readyOps();
            // We first need to call finishConnect() before try to trigger a read(...) or write(...) as otherwise
            // the NIO JDK channel implementation may throw a NotYetConnectedException.
            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();
            }

            // Process OP_WRITE first as we may be able to write some queued buffers and so free memory.
            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();
            }

            // 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;
                }
            }
        } catch (CancelledKeyException ignored) {
            unsafe.close(unsafe.voidPromise());
        }
    }

Netty 默认通过反射将selector 底层的 HashSet 实现转为数组优化
处理每个 ketSet 时都会取到对应的 attachment,即在向 selector注册 io 事件时绑定的经过 Netty 封装后的 channel

10 -reactor线程任务的执行

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
定时任务

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
从定时任务中拉取

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
根据时间,时间相同根据名称

Netty 源码阅读入门实战(四)-NioEventLoop
取nanotime 截止时间前的定时任务

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop

Netty 源码阅读入门实战(四)-NioEventLoop
从普通 taskqueue 中取任务

Netty 源码阅读入门实战(四)-NioEventLoop

相关文章: