NOTE

2.71 3.分配线程及注册selector

1. 要分析的代码 - io.netty.channel.nio.AbstractNioMessageChannel.NioMessageUnsafe#read中有一段逻辑 2. 通过pipeline传播 pipeline.fireChannelRead(readBuf.get(i)) 会从pipe

Java创建于 更新于 historical

这是历史学习笔记,可能存在过时或不完整的理解。

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);
        }
    }
}

4.2.1. 怎么注册的

4.向selector注册读事件.md