五Netty源码分析--3Bootstrap.bind--下

五Netty源码分析--3Bootstrap.bind--下

TAG1.3.1.1.3 register0
AbstractChannel

private void register0(ChannelPromise promise) {
            try {
                // 检查channel是否是open状态(因为在register过程,eventloop外的线程可以执行关闭channel的操作)
                if (!promise.setUncancellable() || !ensureOpen(promise)) {
                    return;
                }
                boolean firstRegistration = neverRegistered; //是否第一次注册
//REGI1 doRegister
                doRegister();
                neverRegistered = false;
                registered = true;

//REGI2 pipeline.invokeHandlerAddedIfNeeded()---
              //触发添加入channel.pipeline上的handlercontext的add操作,然后handler链,可以处理event事件
                pipeline.invokeHandlerAddedIfNeeded();

                safeSetSuccess(promise);
//REGI3 pipeline.fireChannelRegistered()
                pipeline.fireChannelRegistered();
//REGI4 isActive
        		//active状态:只有channel第一次注册时,才会pipeline.fireChannelActive(当底层socket为open或connect时为active)
              //(避免当前channel再次注册时,会fire多个channel的active操作)
                if (isActive()) {
                    if (firstRegistration) {
                        pipeline.fireChannelActive();
                    } else if (config().isAutoRead()) {
                        // This channel was registered before and autoRead() is set. This means we need to begin read
                        // again so that we process inbound data.
                        //
                        // See https://github.com/netty/netty/issues/4805
                        beginRead();
                    }
                }
            } catch (Throwable t) {
                // Close the channel directly to avoid FD leak.
                closeForcibly();
                closeFuture.setClosed();
                safeSetFailure(promise, t);
            }
        }

image-20221206162255821

这里,可以看到此时,Netty的NioServerSocketChannel包装了NIO原生ServerSocketChannelImpl类,并且在初始化时,设置channel感兴趣的事件为ACCEPT。

REGI1 doRegister(NIO原生channel注册到NioEventLoop)
image-20221206153351051
AbstractNioChannel

    @Override
    protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {
//REGI1.1 javaChannel() -----获取原生NIOchannel
//REGI1.2 channel.register------注册channel到selector上
              	//将NIO原生channel注册到原生selector上
                selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
                return;
            } catch (CancelledKeyException e) {
                if (!selected) {
                    // Force the Selector to select now as the "canceled" SelectionKey may still be
                    // cached and not removed because no Select.select(..) operation was called yet.
                    eventLoop().selectNow();
                    selected = true;
                } else {
                    // We forced a select operation on the selector before but the SelectionKey is still cached
                    // for whatever reason. JDK bug ?
                    throw e;
                }
            }
        }
    }
//REGI1.1 javaChannel()

返回Netty的NioServerSocketChannel包装的NIO原生ServerSocketChannelImpl类。

//REGI1.2 channel.register
AbstractNioChannel

//REGI1.1 javaChannel() -----获取原生NIOchannel
//REGI1.2 channel.register------注册channel到selector上
              	//将NIO原生channel注册到原生selector上
                selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
                return;

原生channel.register(0)的原因:

这里原生channel注册到selector上,但是,关注的事件为0(就是不设置关注事件)。因为Netty的NioServerSocketChannel包裹了NIO原生channel,并且已经设置了ACCEPT关注事件,只关注client端的连接,当Netty的channel获取连接就绪channel后,需要对当前channel注册事件,这时获取原生NIOchannel,并注册需要关注的事件。所以,这里先设置原生NIO不关注事件,在后续操作中再设置关注。

AbstractSelectableChannel

    public final SelectionKey register(Selector sel, int ops, Object att) throws ClosedChannelException {
        synchronized (regLock) {
            if (!isOpen())
                throw new ClosedChannelException();
          	//检查validOps()有效事件,是否不包含ops
            if ((ops & ~validOps()) != 0)
                throw new IllegalArgumentException();
            if (blocking)
                throw new IllegalBlockingModeException();
          	//找到当前channel的keys[],非null,且key.selector==sel的SelectionKey
            SelectionKey k = findKey(sel);
          	//如果k不为null,表示当前channel在selector上注册过
            if (k != null) {
              	//设置k关注的事件
                k.interestOps(ops);
              	//SelectionKey的attach为当前nioServerSocketChannel
                k.attach(att);
            }
          	//如果k为null,表示当前channel尚未在selector上注册过,需要新注册
            if (k == null) {
                // New registration
                synchronized (keyLock) {
                    if (!isOpen())
                        throw new ClosedChannelException();
//REGI1.2.1 selector.register
//重新将原生channel注册到selector上
                    k = ((AbstractSelector)sel).register(this, ops, att);
                    addKey(k); //将k加入当前channel对应的key[]集合中
                }
            }
            return k;
        }
    }
//REGI1.2.1 selector.register(原生channel注册到原生selector)
SelectorImpl
  
    protected final SelectionKey register(AbstractSelectableChannel var1, int var2, Object var3) {
        if (!(var1 instanceof SelChImpl)) {
            throw new IllegalSelectorException();
        } else {
          	//创建selectionkey(包括channel和selector的关系)
            SelectionKeyImpl var4 = new SelectionKeyImpl((SelChImpl)var1, this);
          	//将NIOchannel加入selectionkey的attach上
            var4.attach(var3);
            synchronized(this.publicKeys) {
                this.implRegister(var4);
            }
						//设置关注事件var2
            var4.interestOps(var2);
            return var4;
        }
    }
REGI2 pipeline.invokeHandlerAddedIfNeeded()---执行handlerAdd方法
DefaultChannelPipeline

    final void invokeHandlerAddedIfNeeded() {
        assert channel.eventLoop().inEventLoop();
  			//如果channel第一次注册到nioeventloop时
        if (firstRegistration) {
            firstRegistration = false;
            
          //目前,channelpipeline已经注册到eventloop,现在需要在registration完成之前,回调channelhandlers的add方法
            callHandlerAddedForAllHandlers();
        }
    }
    

        private void callHandlerAddedForAllHandlers() {
        final PendingHandlerCallback pendingHandlerCallbackHead;
        synchronized (this) {
            assert !registered;

            // 设置channel已经注册到nioeventloop上
            registered = true;
						//PendingHandlerCallback需要执行handler.add的任务task链的head
            pendingHandlerCallbackHead = this.pendingHandlerCallbackHead;
            // 将this的callback设为null,使其能被GC
            this.pendingHandlerCallbackHead = null;
        }

        // This must happen outside of the synchronized(...) block as otherwise handlerAdded(...) may be called while
        // holding the lock and so produce a deadlock if handlerAdded(...) will try to add another handler from outside
        // the EventLoop.
        PendingHandlerCallback task = pendingHandlerCallbackHead;
/**……………………………………………………………………………………轮询执行pendingTask中ctx的add操作…………………………………………………………………………………………………… */
        while (task != null) {
//REGI2.1 PendingHandlerCallback.execute
            task.execute();
            task = task.next;
        }
    }

其中,PendingHandlerCallback为DefaultChannelPipeline的内部类

image-20221207133908667

此时,执行到这里时,DefaultChannelPipeline中pendingHandlerCallbackHead内包裹的handlerContext,为添加入

image-20230310164231480
//REGI2.1 PendingHandlerCallback.execute
   DefaultChannelPipeline
   
   private final class PendingHandlerAddedTask extends PendingHandlerCallback {

        PendingHandlerAddedTask(AbstractChannelHandlerContext ctx) {
            super(ctx);
        }

        @Override
        public void run() {
            callHandlerAdded0(ctx);
        }

        @Override
        void execute() {
            EventExecutor executor = ctx.executor();
          	//保证在nioeventloop所在线程中执行callHandlerAdded0操作
            if (executor.inEventLoop()) {
//REGI2.1.1 callHandlerAdded0  调用handler的add操作
                callHandlerAdded0(ctx);
            } else {
                try {
                    executor.execute(this);
                } catch (RejectedExecutionException e) {
                    if (logger.isWarnEnabled()) {
                        logger.warn(
                                "Can't invoke handlerAdded() as the EventExecutor {} rejected it, removing handler {}.",
                                executor, ctx.name(), e);
                    }
                    atomicRemoveFromHandlerList(ctx);
                    ctx.setRemoved();
                }
            }
        }
    }
//REGI2.1.1 callHandlerAdded0--->TAG1.2.1.3
DefaultChannelPipeline

 private void callHandlerAdded0(final AbstractChannelHandlerContext ctx) {
        try {
//REGI2.1.1.1 handlerContext.callHandlerAdded
          	//调用handlercontext的handleradd操作
            ctx.callHandlerAdded();
        } catch (Throwable t) {
            boolean removed = false;
            try {
                atomicRemoveFromHandlerList(ctx);
                ctx.callHandlerRemoved();
                removed = true;
            } catch (Throwable t2) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Failed to remove a handler: " + ctx.name(), t2);
                }
            }

            if (removed) {
                fireExceptionCaught(new ChannelPipelineException(
                        ctx.handler().getClass().getName() +
                        ".handlerAdded() has thrown an exception; removed.", t));
            } else {
                fireExceptionCaught(new ChannelPipelineException(
                        ctx.handler().getClass().getName() +
                        ".handlerAdded() has thrown an exception; also failed to remove.", t));
            }
        }
    }
//REGI2.1.1.1 handlerContext.callHandlerAdded--->TAG1.2.1.3.1
AbstractChannelHandlerContext

    final void callHandlerAdded() throws Exception {
  			//首先设置handlerContext的状态为ADD-COMPLETE
        if (setAddComplete()) {
//HanAdd1 handler().handlerAdded(this)
            handler().handlerAdded(this);
        }
    }

    final boolean setAddComplete() {
        for (;;) {
            int oldState = handlerState;
            if (oldState == REMOVE_COMPLETE) {
                return false;
            }
            // 设置状态为ADD_COMPLETE
            if (HANDLER_STATE_UPDATER.compareAndSet(this, oldState, ADD_COMPLETE)) {
                return true;
            }
        }
    }
//HanAdd1 handler().handlerAdded(this)(调用handler.handlerAdded)--channelInitializer的执行
public interface ChannelHandler {

    /**
     * Gets called after the {@link ChannelHandler} was added to the actual context and it's ready to handle events.
     */
    void handlerAdded(ChannelHandlerContext ctx) throws Exception;

当handler被真正添加入handlerContext后,会调用channelHandler.handlerAdded操作,之后,handler才能真正的准备好处理事件。

对于ChannelInitializer实现类来说:

ChannelInitializer
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        if (ctx.channel().isRegistered()) {
//HanADD1.1 ChannelInitializer.initChannel
            //初始化channel---channelInitializer类的initChannel方法,会将childhandler添加入channelPipeline中
            if (initChannel(ctx)) {
//HanAdd1.2 removeState---略
                // We are done with init the Channel, removing the initializer now.
                removeState(ctx);
            }
        }
    }
//HanADD1.1 ChannelInitializer.initChannel(跳过)
ChannelInitializer
    private boolean initChannel(ChannelHandlerContext ctx) throws Exception {
        if (initMap.add(ctx)) { // Guard against re-entrance.
            try {
//HanADD1.1.1 initChannel((C) ctx.channel())
                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 {
                ChannelPipeline pipeline = ctx.pipeline();
                if (pipeline.context(this) != null) {
//HanAdd1.1.2 pipeline.remove(channelInitializer)
                  //将ChannelInitializer从pipeline中移除
                    pipeline.remove(this);
                }
            }
            return true;
        }
        return false;
    }
//HanADD1.1.1 initChannel((C) ctx.channel())---(serverBootstrap匿名channelInitializer,创建并添加ServerBootstrapAcceptor)

ctx.channel为handlerContext所绑定的channel;

这里,initChannel方法会执行ServerBootstrap中创建匿名类ServerBootstrap$1的initChannel方法。

image-20221207141047377

config.handler获取向ServerBootstrap.handler(LoggingHandler)配置的handler,加入pipeline中。

//将runnable转换为task,加入NioEventLoop的任务队列中
ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });
            }
image-20221207141855125

将pipeline.addLast(ServerBootstrapAcceptor)的操作,作为task,加入NioEventLoop的任务队列中---addTask(task)中。当nioeventloop绑定线程执行时,wakeup操作,唤醒nioeventloop内阻塞select操作,执行任务队列中任务。详见[StartThread1 NioEventLoop.run](#StartThread1 NioEventLoop.run)

该执行过程,会向pipeline中添加ServerBootstrapAcceptor类,其中currentChildHandler为Server启动程序中,添加的自定义channelInitializer类

image-20221207131138025
//HanAdd1.1.2 pipeline.remove(channelInitializer)--略

移除自定义的ChannelInitializer。

DefaultChannelPipeline
    @Override
    public final ChannelPipeline remove(ChannelHandler handler) {
        remove(getContextOrDie(handler));
        return this;
    }
    
    public final ChannelPipeline remove(ChannelHandler handler) {
        remove(getContextOrDie(handler));
        return this;
    }
    
        private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) {
        assert ctx != head && ctx != tail;

        synchronized (this) {
            atomicRemoveFromHandlerList(ctx);

            // If the registered is false it means that the channel was not registered on an eventloop yet.
            // In this case we remove the context from the pipeline and add a task that will call
            // ChannelHandler.handlerRemoved(...) once the channel is registered.
            if (!registered) {
                callHandlerCallbackLater(ctx, false);
                return ctx;
            }

            EventExecutor executor = ctx.executor();
            if (!executor.inEventLoop()) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        callHandlerRemoved0(ctx);
                    }
                });
                return ctx;
            }
        }
        callHandlerRemoved0(ctx);
        return ctx;
    }

这个逻辑,同TAG1.2.1 ChannelPipeline.addLast逻辑相同,省略

REGI3 pipeline.fireChannelRegistered()---pipeline上链式触发
image-20230310164325124

触发channel绑定的pipeline.fireChannelRegistered()方法,触发pipeline上的handler链上的处理链。(REGI2过程,执行过channel.pipeline上context.add操作后,handler此时可以处理event事件)。

AbstractChannel
                pipeline.fireChannelRegistered();
DefaultChannelPipeline
    @Override
    public final ChannelPipeline fireChannelRegistered() {
  			//pipeline中保存context链中的head和tail,inbound操作,从head开始调用
        AbstractChannelHandlerContext.invokeChannelRegistered(head);
        return this;
    }
AbstractChannelHandlerContext
   static void invokeChannelRegistered(final AbstractChannelHandlerContext next) {
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
          //context中链式调用
            next.invokeChannelRegistered();
        } else {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    next.invokeChannelRegistered();
                }
            });
        }
    }
image-20221207152508051

可知,此时,server端channePipeline上handlerContext链如下:

HeadContext------>LoggingHandler------>TailContext
AbstractChannelHandlerContext
    private void invokeChannelRegistered() {
        if (invokeHandler()) {
            try {
              	//(ChannelInboundHandler) handler()获取的是pipeline
                ((ChannelInboundHandler) handler()).channelRegistered(this);
            } catch (Throwable t) {
                notifyHandlerException(t);
            }
        } else {
            fireChannelRegistered();
        }
    }
DefaultChannelPipeline
        @Override
        public void channelRegistered(ChannelHandlerContext ctx) {
            invokeHandlerAddedIfNeeded(); //调用handleradd
            ctx.fireChannelRegistered();
        }

递归调用:context.fireXXX,其内的findContextInbound遍历context中对应事件的handler

AbstractChannelHandlerContext
    @Override
    public ChannelHandlerContext fireChannelRegistered() {
  			//findContextInbound(MASK_CHANNEL_REGISTERED)实现context链中的遍历,找到关注registered的handlerContext
        invokeChannelRegistered(findContextInbound(MASK_CHANNEL_REGISTERED));
        return this;
    }
image-20221207153924345
AbstractChannelHandlerContext
   static void invokeChannelRegistered(final AbstractChannelHandlerContext next) {
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
          
            next.invokeChannelRegistered();
        } else {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    next.invokeChannelRegistered();
                }
            });
        }
    }
AbstractChannelHandlerContext
    private void invokeChannelRegistered() {
        if (invokeHandler()) {
            try {
              //调用实际handler的channelRegistered方法
                ((ChannelInboundHandler) handler()).channelRegistered(this);
            } catch (Throwable t) {
                notifyHandlerException(t);
            }
        } else {
            fireChannelRegistered();
        }
    }
LoggingHandler
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        if (logger.isEnabled(internalLevel)) {
            logger.log(internalLevel, format(ctx, "REGISTERED"));
        }
  			//handlercontext的链式调用
        ctx.fireChannelRegistered();
    }

以上的pipeline上的链式context执行流程如下:

image-20230310164412021

详细过程见[17.5.3.3 AbstractChannelHandlerContext.fireChannelRead流程](#17.5.3.3 AbstractChannelHandlerContext.fireChannelRead流程)

REGI4 isActive(channel已经注册过,active状态的处理)
image-20221207145125092
1 channel已经注册到NioEventLoop中---状态为registered
2 然后判断channel是否为active:
		2.1 如果channel第一次注册,执行pipeline.fireChannelActive;
		2.2 如果channel不是第一次注册,执行beginRead,准备读
TAG2 ChannelFuture.channel
image-20221207161350300

返回server端parentchannel。

channeFutrue和channelPromise,详看netty组件。

TAG3 doBind0--绑定端口
image-20221207161635305

在server端,regFuture尚未完成,因此执行channelFuture的异步机制监听,等待任务完成时,执行自定义operationComplete内的doBind0()绑定。

image-20221207162622287

AbstractBootstrap

    private static void doBind0( final ChannelFuture regFuture, final Channel channel,
            final SocketAddress localAddress, final ChannelPromise promise) {

        // This method is invoked before channelRegistered() is triggered.  Give user handlers a chance to set up
        // the pipeline in its channelRegistered() implementation.
        channel.eventLoop().execute(new Runnable() {
            @Override
            public void run() {
              //当channel初始化并注册到nioeventloop成功后,会执行channe绑定端口bind操作
                if (regFuture.isSuccess()) {
                    channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
                } else {
                    promise.setFailure(regFuture.cause());
                }
            }
        });
    }
AbstractChannel
   public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
        return pipeline.bind(localAddress, promise);
    }
DefaultChannelPipeline
    @Override
    public final ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
  			//outbound类型的bind,从tailContext开始
        return tail.bind(localAddress, promise);
    }
AbstractChannelHandlerContext
    @Override
    public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) {
        if (localAddress == null) {
            throw new NullPointerException("localAddress");
        }
        if (isNotValidPromise(promise, false)) {
            // cancelled
            return promise;
        }

//TAG3.1 findContextOutbound(MASK_BIND)
        final AbstractChannelHandlerContext next = findContextOutbound(MASK_BIND);
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
//TAG3.2 context.invokeBind
            next.invokeBind(localAddress, promise);
        } else {
            safeExecute(executor, new Runnable() {
                @Override
                public void run() {
                    next.invokeBind(localAddress, promise);
                }
            }, promise, null);
        }
        return promise;
    }
TAG3.1 findContextOutbound(MASK_BIND)

找到bind事件的handlerContext。

AbstractChannelHandlerContext
    private AbstractChannelHandlerContext findContextOutbound(int mask) {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.prev;
          //当不包含mask(BIND)感兴趣事件时,遍历下一个handlerContext
        } while ((ctx.executionMask & mask) == 0);
        return ctx;
    }

遍历找到HeadContext,其进行实际的bind(localAddress)

image-20221207164431757
TAG3.2 context.invokeBind
AbstractChannelHandlerContext
    private void invokeBind(SocketAddress localAddress, ChannelPromise promise) {
        if (invokeHandler()) {
            try {
                ((ChannelOutboundHandler) handler()).bind(this, localAddress, promise);
            } catch (Throwable t) {
                notifyOutboundHandlerException(t, promise);
            }
        } else {
            bind(localAddress, promise);
        }
    }
DefaultChannelPipeline--->HeadContext
        @Override
        public void bind(
                ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) {
//TAG3.2.1 unsafe.bind
            unsafe.bind(localAddress, promise);
        }
//TAG3.2.1 unsafe.bind
AbstractChannel-->AbstractUnsafe
        @Override
        public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
            assertEventLoop();

            if (!promise.setUncancellable() || !ensureOpen(promise)) {
                return;
            }

            // See: https://github.com/netty/netty/issues/576
            if (Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) &&
                localAddress instanceof InetSocketAddress &&
                !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress() &&
                !PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) {
                // Warn a user about the fact that a non-root user can't receive a
                // broadcast packet on *nix if the socket is bound on non-wildcard address.
                logger.warn(
                        "A non-root user can't receive a broadcast packet if the socket " +
                        "is not bound to a wildcard address; binding to a non-wildcard " +
                        "address (" + localAddress + ") anyway as requested.");
            }

  				//判断channel是否被active激活(此时socket尚未open,因此为false)
            boolean wasActive = isActive();
            try {
//BIND1 doBind(localAddress)
                doBind(localAddress);
            } catch (Throwable t) {
                safeSetFailure(promise, t);
                closeIfClosed();
                return;
            }
//BIND2 pipeline.fireChannelActive()
						//当channel的socket刚刚被active时。然后再执行fireChannelActive
            if (!wasActive && isActive()) {
                invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        pipeline.fireChannelActive();
                    }
                });
            }

            safeSetSuccess(promise);
        }
BIND1 doBind(localAddress)
NioServerSocketChannel
    @Override
    protected void doBind(SocketAddress localAddress) throws Exception {
        if (PlatformDependent.javaVersion() >= 7) {
          	//获取NIO原生serverSocketChannel对象,执行bind绑定端口和地址
            javaChannel().bind(localAddress, config.getBacklog());
        } else {
            javaChannel().socket().bind(localAddress, config.getBacklog());
        }
    }

image-20221207165459950

BIND2 pipeline.fireChannelActive()---channel绑定端口后active激活

执行pipeline上的触发channel的active激活。

TAG4 channelfuture异步机制--todo

channelFuture.addListener,是netty实现异步操作的核心。

posted @ 2023-03-10 17:27  LeasonXue  阅读(27)  评论(0编辑  收藏  举报