前置说明
本文主要记录Netty中的一些主要的关键时间点,是理解Netty 和 事件驱动的关键。也是阅读Netty源码的指导。
代码来源:Netty 4.1.77
本文涉及到的角色:
角色:主线程,主Reactor线程(bossGroup中的EventLoop), 从Reactor线程(workGroup中的EventLoop),结合Reactor编码模型理解
PS:Netty中的主要事件节点不断完善中,看看后面要不要拆成多篇。。。
主Reactor线程的启动时间点
主线程调用ServerBootStrap.bind方法,会通过io.netty.bootstrap.AbstractBootstrap#initAndRegister方法,先初始化NioServerSocktChannel,然后把NioServerSocktChannel注册到主Reactor线程组中的一个主Reactor线程上
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
// 创建和初始化
channel = channelFactory.newChannel();
init(channel);
} catch (Throwable t) {
if (channel != null) {
// channel can be null if newChannel crashed (eg SocketException("too many open files"))
channel.unsafe().closeForcibly();
}
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
//注册
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
最终会调用该主Reactor线程的注册方法进行注册:io.netty.channel.AbstractChannel.AbstractUnsafe#register,
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
...
//检查相关代码忽略
AbstractChannel.this.eventLoop = eventLoop;
if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
//当前是Main线程调用,所以提交任务到ServerChannel对应的Reactor线程
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
异常处理忽略。。。
}
}
}
由于是主线程调用的该方法,所以会通过io.netty.util.concurrent.SingleThreadEventExecutor#execute(java.lang.Runnable) -> io.netty.util.concurrent.SingleThreadEventExecutor#execute(java.lang.Runnable, boolean) 提交一个异步任务到该主Reactor线程,
private void execute(Runnable task, boolean immediate) {
boolean inEventLoop = inEventLoop();
addTask(task); //把注册任务提交到主Reactor线程的任务队列
if (!inEventLoop) {//当前是Main线程,需要启动主Reactor线程
startThread();
if (isShutdown()) {
boolean reject = false;
try {
if (removeTask(task)) {
reject = true;
}
} catch (UnsupportedOperationException e) {
}
if (reject) {
reject();
}
}
}
if (!addTaskWakesUp && immediate) {
wakeup(inEventLoop);
}
}
然后主线程调用io.netty.util.co