NOTE
2.71 3.分配线程及注册selector
1. 要分析的代码 - io.netty.channel.nio.AbstractNioMessageChannel.NioMessageUnsafe#read中有一段逻辑 2. 通过pipeline传播 pipeline.fireChannelRead(readBuf.get(i)) 会从pipe
这是历史学习笔记,可能存在过时或不完整的理解。
1. 要分析的代码
- io.netty.channel.nio.AbstractNioMessageChannel.NioMessageUnsafe#read中有一段逻辑
//...
for (int i = 0; i < size; i ++) {
readPending = false;
pipeline.fireChannelRead(readBuf.get(i));
}
//...
2. 通过pipeline传播
pipeline.fireChannelRead(readBuf.get(i))会从pipeline中开始往后传播
3. 经过ServerBootstrapAcceptor
io.netty.bootstrap.ServerBootstrap#init中有一段逻辑
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
这里在pipeline中添加了ServerBootstrapAcceptor,那么上面的fireChannelRead也会到达ServerBootstrapAcceptor
4. 分析ServerBootstrapAcceptor#channelRead
public void channelRead(ChannelHandlerContext ctx, Object msg) {
final Channel child = (Channel) msg;
//将用户自定的childHanlder添加进pipeline里
child.pipeline().addLast(childHandler);
//设置options和attrs
setChannelOptions(child, childOptions, logger);
for (Entry<AttributeKey<?>, Object> e: childAttrs) {
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
}
try {
//选择NioEventLoop并注册selector
//io.netty.channel.AbstractChannel.AbstractUnsafe#register
childGroup.register(child).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
forceClose(child, future.cause());
}
}
});
} catch (Throwable t) {
forceClose(child, t);
}
}
4.1. 添加childHandler
.childHandler(new ChannelInitializer<SocketChannel>()
{
@Override
protected void initChannel(SocketChannel channel) throws Exception
{
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(new LoggingHandler(LogLevel.INFO));
}
});
添加的是ChannelInitializer,我们看看他的handlerAdded方法
- handlerAdded方法
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel().isRegistered()) {
//会调用initChannel
initChannel(ctx);
}
}
- initChannel
private boolean initChannel(ChannelHandlerContext ctx) throws Exception {
if (initMap.putIfAbsent(ctx, Boolean.TRUE) == null) { // Guard against re-entrance.
try {
//会调用我们的ChannelInitializer的initChannel方法
initChannel((C) ctx.channel());
} catch (Throwable cause) {
// Explicitly call exceptionCaught(...) as we removed the handler before calling initChannel(...).
// We do so to prevent multiple calls to initChannel(...).
exceptionCaught(ctx, cause);
} finally {
remove(ctx);
}
return true;
}
return false;
}
4.2. 选择NioEventLoop并注册selector
//...
//调用SingleThreadEventLoop的register
childGroup.register(child)//...
//...
- SingleThreadEventLoop#register(io.netty.channel.Channel)
public ChannelFuture register(Channel channel) {
return register(new DefaultChannelPromise(channel, this));
}
@Override
public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
//调用io.netty.channel.AbstractChannel.AbstractUnsafe#register
promise.channel().unsafe().register(this, promise);
return promise;
}
- io.netty.channel.AbstractChannel.AbstractUnsafe#register
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
if (eventLoop == null) {
throw new NullPointerException("eventLoop");
}
if (isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
if (!isCompatible(eventLoop)) {
promise.setFailure(
new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
return;
}
//把当前channel关联到NioEventGroupLoop
AbstractChannel.this.eventLoop = eventLoop;
if (eventLoop.inEventLoop()) {
//注册
register0(promise);
} else {
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
logger.warn(
"Force-closing a channel whose registration task was not accepted by an event loop: {}",
AbstractChannel.this, t);
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
}