Netty源码解析(五) —— 客户端channel如何完成注册

上一篇我们拿到所有的accept到的channel之后,我们回头看事件通知
还记得io.netty.bootstrap.ServerBootstrap#init服务端启动的时候,

                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        //pipline会默认添加一个acceptor,是设置给ServerBootStrap的
                        //ServerBootstrapAcceptor  专门处理新连接accept进来的处理
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });

这里会给channel添加一个ServerBootstrapAcceptor,先不管这个accept,他是一个InBound类型,接着上面我们来看事件通知pipeline.fireChannelRead(readBuf.get(i));

    /**
     * 有数据读入的时候会调用(InBound)  也可以手动调用
     * @param msg 客户端连接的channel
     * @return
     */
    @Override
    public final ChannelPipeline fireChannelRead(Object msg) {
        //pipline节点类的静态方法 穿进去的head
        AbstractChannelHandlerContext.invokeChannelRead(head, msg);
        return this;
    }

AbstractChannelHandlerContext是pipline的一个链表节点,里面维护一个InBound或者OutBound 的adapter

    /**
     * 静态方法
     * @param next  第一次调用next是head   之后依次链表往下找
     * @param msg 客户端连接的channel
     */
    static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
        final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
            //调用pipline节点的方法
            next.invokeChannelRead(m);
        } else {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    next.invokeChannelRead(m);
                }
            });
        }
    }
    /**
     * @param msg 包含客户端channel的一个对象
     */
    private void invokeChannelRead(Object msg) {
        if (invokeHandler()) {
            try {
                //进入到当前的带调用节点 this  =  head->..ServerBootstrapAcceptor..->tail
                //拿到当前节点包装的handler  调用handler的channelRead
                //第一次走的是HeadContext
                ((ChannelInboundHandler) handler()).channelRead(this, msg);
            } catch (Throwable t) {
                notifyHandlerException(t);
            }
        } else {
            fireChannelRead(msg);
        }
    }

这里先走HeadContext节点,然后再走ServerBootstrapAcceptor.channelRead方法,那么我们可以断定,客户端新连接的注册就在这个方法完成的
io.netty.bootstrap.ServerBootstrap.ServerBootstrapAcceptor#channelRead

        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            //msg 新连接进来会传播事件 传递进来的channel对象
            final Channel child = (Channel) msg;
            //取出来新连接的pipLine 把Server端配置的handler添加进去
            child.pipeline().addLast(childHandler);
            setChannelOptions(child, childOptions, logger);

            for (Entry<AttributeKey<?>, Object> e: childAttrs) {
                child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
            }
            try {
                //childGroup其实就是worker NioEventLoopGroup,去注册客户端的channel对象
                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);
            }
        }

io.netty.channel.MultithreadEventLoopGroup#register(io.netty.channel.Channel)

    @Override
    public ChannelFuture register(Channel channel) {
        return next().register(channel);
    }

这里需要解释一下,NioEventLoopGroup.next()会调用线程选择器chooser,来选择一个NioEventLoop对象完成channel的注册
io.netty.channel.SingleThreadEventLoop#register(io.netty.channel.Channel)

    /**
     * 注册channel
     * @param channel
     * @return
     */
    @Override
    public ChannelFuture register(Channel channel) {
        return register(new DefaultChannelPromise(channel, this));
    }
    @Override
    public ChannelFuture register(final ChannelPromise promise) {
        ObjectUtil.checkNotNull(promise, "promise");
        //转交给unsafe来进行注册
        promise.channel().unsafe().register(this, promise);
        return promise;
    }

io.netty.channel.AbstractChannel.AbstractUnsafe#register

        /**
         * 注册channel到selector
         * @param eventLoop
         * @param promise
         */
        @Override
        public final void register(EventLoop eventLoop, final ChannelPromise promise) {

            .....

            //保存事件处理线程
            AbstractChannel.this.eventLoop = eventLoop;
            /**
             * 在工作线程知己进行注册
             */
            if (eventLoop.inEventLoop()) {
                //注册channel
                register0(promise);
            } else {
                try {
                    //否则执行task任务  添加到队列  异步进行调度
                    eventLoop.execute(new Runnable() {
                        @Override
                        public void run() {
                            register0(promise);
                        }
                    });
                } catch (Throwable t) {
                  ....
            }
        }

io.netty.channel.AbstractChannel.AbstractUnsafe#register0

        private void register0(ChannelPromise promise) {
            try {
                if (!promise.setUncancellable() || !ensureOpen(promise)) {
                    return;
                }
                boolean firstRegistration = neverRegistered;
                //执行注册channel的逻辑
                doRegister();
                neverRegistered = false;
                registered = true;

                //通知pipline添加操作
                pipeline.invokeHandlerAddedIfNeeded();

                safeSetSuccess(promise);
                //通知pipline registe事件
                pipeline.fireChannelRegistered();

                if (isActive()) {
                    if (firstRegistration) {
                        //通知pipline的active事件  header->tail  active
                        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);
            }
        }

先看io.netty.channel.AbstractChannel#doRegister方法,这个是执行注册的方法

    @Override
    protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {
                //注册java的nio channel到selector   ops=0表示不关心任何事件,
                //只是注册进去   att=this  添加attachments = netty的niochannel
                selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
                return;

可以看到是调用java原生的channel来注册到NioEventLoop中的selector中去,并且设置attachment是channel(所有selectKey.attachment()拿到的就是channel本身),注册关心事件0,标识不关心任何事件
接着看注册完了之后的通知事件io.netty.channel.Channel#isActive

    /**
     * 判断channel是否是激活的
     * 对于客户端channel来说,channel是打开并且是连接状态的
     * @return
     */
    @Override
    public boolean isActive() {
        SocketChannel ch = javaChannel();
        return ch.isOpen() && ch.isConnected();
    }

之后调用pipeline.fireChannelActive();

    @Override
    public final ChannelPipeline fireChannelActive() {
        AbstractChannelHandlerContext.invokeChannelActive(head);
        return this;
    }

最终进入HeadContext的channelActive方法

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            ctx.fireChannelActive();

            //注册read关心事件
            readIfIsAutoRead();
        }
        private void readIfIsAutoRead() {
            if (channel.config().isAutoRead()) {
                channel.read();
            }
        }

io.netty.channel.AbstractChannel#read

    @Override
    public Channel read() {
        pipeline.read();
        return this;
    }

又调用pipline的read方法,继续跟进

    @Override
    public final ChannelPipeline read() {
        tail.read();
        return this;
    }

调用TailContext的read方法

    @Override
    public ChannelHandlerContext read() {
        final AbstractChannelHandlerContext next = findContextOutbound();
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
            //调用invokeRead方法
            next.invokeRead();
        } else {
            Runnable task = next.invokeReadTask;
            if (task == null) {
                next.invokeReadTask = task = new Runnable() {
                    @Override
                    public void run() {
                        next.invokeRead();
                    }
                };
            }
            executor.execute(task);
        }

        return this;
    }

findContextOutbound()会从tail开始往前找到HeadContext

    private void invokeRead() {
        if (invokeHandler()) {
            try {
                ((ChannelOutboundHandler) handler()).read(this);
            } catch (Throwable t) {
                notifyHandlerException(t);
            }
        } else {
            read();
        }
    }

最终进入headContext的read方法

        @Override
        public void read(ChannelHandlerContext ctx) {
            unsafe.beginRead();
        }

io.netty.channel.AbstractChannel.AbstractUnsafe#beginRead

        @Override
        public final void beginRead() {
            assertEventLoop();

            if (!isActive()) {
                return;
            }

            try {
                //真正开始read 注册关心事件
                doBeginRead();
            } catch (final Exception e) {
                invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        pipeline.fireExceptionCaught(e);
                    }
                });
                close(voidPromise());
            }
        }

io.netty.channel.nio.AbstractNioChannel#doBeginRead

    @Override
    protected void doBeginRead() throws Exception {
        // Channel.read() or ChannelHandlerContext.read() was called
        final SelectionKey selectionKey = this.selectionKey;
        if (!selectionKey.isValid()) {
            return;
        }

        readPending = true;

        //取出来构造参数传进来的ops  readInterestOp就是构造传进来
        final int interestOps = selectionKey.interestOps();
        if ((interestOps & readInterestOp) == 0) {
            //注册感兴趣事件
            selectionKey.interestOps(interestOps | readInterestOp);
        }
    }

对于这个感兴趣的事件,是channel对象在构造时候传进去的AbstractNioByteChannel(客户端channel)

    protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
        //关心read事件
        super(parent, ch, SelectionKey.OP_READ);
    }

猜你喜欢

转载自blog.csdn.net/u011702633/article/details/81980078