Netty服务端源码阅读笔记(四)ServerBootstrap(3)

16 篇文章 0 订阅

接上章节

Netty服务端源码阅读笔记(四)ServerBootstrap(1)

Netty服务端源码阅读笔记(四)ServerBootstrap(2)

 

serverBootStrap.bind() --> initAndRegister() --> NioEventLoop.register(channel)

NioEventLoop注册NioServerSocketChannel

    public ChannelFuture register(Channel channel) {
        return register(new DefaultChannelPromise(channel, this));
    }
    public ChannelFuture register(final ChannelPromise promise) {
        ObjectUtil.checkNotNull(promise, "promise");
        promise.channel().unsafe().register(this, promise);
        return promise;
    }

  跟到 io.netty.channel.AbstractChannel.AbstractUnsafe#register   

走到这,才算真正第一次调用NioEventLoop.execute方法, 此后NioEventLoop才有了自己的线程,开始死循环select和处理任务,以后再调用execute就只是往任务队列添加

       public final void register(EventLoop eventLoop, final ChannelPromise promise) {

            // 这里实现了channel与eventLoop的绑定
            AbstractChannel.this.eventLoop = eventLoop;

            // 判断当前正在执行的线程是否是当前eventLoop所绑定的线程
            if (eventLoop.inEventLoop()) {
                // 若当前线程是eventLoop绑定线程,则直接让这个线程来完成注册操作
                register0(promise);
            } else {
                // 当前线程不是eventLoop绑定线程,则调用NioeventLoop.execute方法执行注册
                // 前篇看过这个方法,如果NioEventLoop还未绑定线程,则创建新线程并绑定eventLoop,然后使用这个新创建的eventLoop线程来完成注册
                try {
                    eventLoop.execute(new Runnable() {
                        @Override
                        public void run() {
                            register0(promise);
                        }
                    });
                } catch (Throwable t) {
                    closeForcibly();
                    closeFuture.setClosed();
                    safeSetFailure(promise, t);
                }
            }
        }

        private void register0(ChannelPromise promise) {
            try {
                // check if the channel is still open as it could be closed in the mean time when the register
                // call was outside of the eventLoop
                if (!promise.setUncancellable() || !ensureOpen(promise)) {
                    return;
                }
                boolean firstRegistration = neverRegistered;
                // 正儿八经的注册方法,终于到了
                doRegister();
                // 修改状态值
                neverRegistered = false;
                registered = true;

                // 触发handlerAdded()方法的执行
                pipeline.invokeHandlerAddedIfNeeded();

                safeSetSuccess(promise);
                // 触发channelRegistered()方法的执行
                pipeline.fireChannelRegistered();

                // 若当前channel是激活状态
                // 触发channelActive()的执行,在这里真正关注事件
                if (isActive()) {
                    if (firstRegistration) {
                        pipeline.fireChannelActive();
                    } else if (config().isAutoRead()) {
                        beginRead();
                    }
                }
            } catch (Throwable t) {
                // Close the channel directly to avoid FD leak.
                closeForcibly();
                closeFuture.setClosed();
                safeSetFailure(promise, t);
            }
        }

io.netty.channel.nio.AbstractNioChannel#doRegister,原生nio操作

 protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {
                // 其实netty的channel的注册,本质上是原生的nio的channel的注册
                selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
                return;
            } catch (CancelledKeyException e) {
                if (!selected) {
                    eventLoop().selectNow();
                    selected = true;
                } else {
                    throw e;
                }
            }
        }
    }

这里是注册,但是没有关注任何事件,在随后调用ChannelActive(HeadContext)或beginRead中真正关注事件

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

        readPending = true;

        // 目前什么也没关注,readInterestOp为new Channel()时默认设置的关注事件
        // serverChannel默认设置关注accept,socketchannel默认设置关注read
        final int interestOps = selectionKey.interestOps();
        if ((interestOps & readInterestOp) == 0) {
            selectionKey.interestOps(interestOps | readInterestOp);
        }
    }

以handlerAdded()方法的执行为例,看看handler中的回调如何被调用
 pipeline.invokeHandlerAddedIfNeeded();

里边遍历执行pendingHandlerCallbackHead中的handler.handlerAdded()方法,pendingHandlerCallbackHead是个链表,在上章看过,还未注册前,pipeLine.addLast就是将handler放入了这个链表中

   final void invokeHandlerAddedIfNeeded() {
        assert channel.eventLoop().inEventLoop();
        if (firstRegistration) {
            firstRegistration = false;
            // We are now registered to the EventLoop. It's time to call the callbacks for the ChannelHandlers,
            // that were added before the registration was done.
            callHandlerAddedForAllHandlers();
        }
    }

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

            // This Channel itself was registered.
            registered = true;

            pendingHandlerCallbackHead = this.pendingHandlerCallbackHead;
            // Null out so it can be GC'ed.
            this.pendingHandlerCallbackHead = null;
        }

        PendingHandlerCallback task = pendingHandlerCallbackHead;
        while (task != null) {
            // 这里就是调用handler.handleradded()
            task.execute();
            task = task.next;
        }
    }

// initChannel调用的地方到了,就是channel第一次注册时,调用的那个初始化方法
public abstract class ChannelInitializer<C extends Channel> extends ChannelInboundHandlerAdapter {
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        if (ctx.channel().isRegistered()) {
            if (initChannel(ctx)) {
               removeState(ctx);
            }
        }
    }
}

总结之:这里很重要,一切一切的开始,服务端ServerSocketChannel在parentGroup中选择一个NioEventLoop,调用其execute()来进行注册,execute执行时,创建线程绑定NioEventLoop,注册到selector,并执行定义的ChannelInitializer中initChannel()方法初始化handler,这个NioEventLoop的线程开始死循环执行select和普通任务,不停检测其所绑定的channel就绪事件,并处理。

刚启动当然这个parentGroup和childGroup中NioEventLoop中只绑定了服务端channel,当接受到客户端连接时,这个服务端channel会调用它的处理器handler, 处理器中有一个ServerBootstrapAcceptor处理器,这个处理器的channelRead方法,初始化子channel,从childGroup中选择一个NioEventLoop注册这个子channel,相应的又开始创建线程不停检测处理子channel的事件。

至此parentGroup处理客户端连接,childGroup处理客户端读写事件,这个模式就开始运转了

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值