1 NioEventLoop概述

总述

2 NioEventLoop创建概述










对应


对应


对应


对应

3 ThreadPerTaskThread
2 服务端Channel的创建




bind 对应样例的

跟进调试





通过反射创建的 channel
看看 channelFactory


反射创建服务端 Channel

首先



创建完毕了



ANC







4 创建NioEventLoop线程









5 创建线程选择器




先看看普通的


再看幂2的


循环取数组索引下标,& 比取模性能更高
6 NioEventLoop的启动



对应是


对应是













7 NioEventLoop执行概述
8 检测IO事件


对应的源码为





对应的源码为



执行至此,说明已进行了一次阻塞式的 select 操作

产生空轮询的判断

当空轮询次数大于阈值

阈值定义


阈值

避免空轮询的再次发生

创建新选择器

获取旧选择器的所有 key 值

netty 包装的 channel

将之前的 key 事件解除,并绑定新的选择器和对应的事件

更新选择器的 key

至此,解决了空轮bug
9 处理IO事件



原生JDK创建一个 selector


单线程处理,其实不需要两个数组,后续版本已经是一个数组

只需关注

根本不需要此三个方法


通过反射

即此类


继续反射流程

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





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线程任务的执行








定时任务





从定时任务中拉取


根据时间,时间相同根据名称

取nanotime 截止时间前的定时任务



从普通 taskqueue 中取任务

作者:芥末无疆sss
链接:https://www.jianshu.com/p/dd9afddaec08
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
随时随地看视频