netty启动源码3

接着执行如下代码:
ChannelFuture future = serverBootstrap.bind(8088).sync();
这里是真正的启动源码的地方:这行代码做的事情太多太多太多…了
跟踪源码到AbstractBootstrap类的如下方法:

    private ChannelFuture doBind(final SocketAddress localAddress) {
        //初始化和注册
        final ChannelFuture regFuture = initAndRegister();
        final Channel channel = regFuture.channel();
        if (regFuture.cause() != null) {
            return regFuture;
        }

        if (regFuture.isDone()) {
            // At this point we know that the registration was complete and successful.
            ChannelPromise promise = channel.newPromise();
            doBind0(regFuture, channel, localAddress, promise);
            return promise;
        } else {
            // Registration future is almost always fulfilled already, but just in case it's not.
            final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
            regFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    Throwable cause = future.cause();
                    if (cause != null) {
                        // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
                        // IllegalStateException once we try to access the EventLoop of the Channel.
                        promise.setFailure(cause);
                    } else {
                        // Registration was successful, so set the correct executor to use.
                        // See https://github.com/netty/netty/issues/2586
                        promise.registered();

                        doBind0(regFuture, channel, localAddress, promise);
                    }
                }
            });
            return promise;
        }
    }

从这里开始先跟踪如下代码:
final ChannelFuture regFuture = initAndRegister();
以下代码都是该方法的内容
跟踪代码:

    //初始化并注册
    final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            //通过反射创建NioServerSocketChannel
            //channelFactory=new ReflectiveChannelFactory  ---> constructor=NioServerSocketChannel.class.getConstructor();
            //channel=NioServerSocketChannel
            channel = channelFactory.newChannel();
            init(channel);
        } catch (Throwable t) {
            if (channel != null) {
                // channel can be null if newChannel crashed (eg SocketException("too many open files"))
                channel.unsafe().closeForcibly();
                // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
                return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
            }
            // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
            return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
        }
        //config().group()==bossGroup  ===》 EventLoopGroup bossGroup=new NioEventLoopGroup(1);
        //register开启了事件轮询线程
        //config().group()  boosGroup
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }
        return regFuture;
    }

这里创建了channel=NioServerSocketChannel这里为什么是这个实体可以看之前上面有说过然后看init()方法:

 @Override
    void init(Channel channel) throws Exception {

        //channel=NioServerSocketChannel

        //options0  获取的是用户自己设置的tcp参数  ServerBootstrap.option(ChannelOption.SO_BACKLOG,128)
        final Map<ChannelOption<?>, Object> options = options0();
        synchronized (options) {
            //设置用户设置的tcp参数
            setChannelOptions(channel, options, logger);
        }
        //attrs0()  ServerBootstrap.attr()  获取用户设置的attr参数
        final Map<AttributeKey<?>, Object> attrs = attrs0();
        synchronized (attrs) {
            for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
                @SuppressWarnings("unchecked")
                AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
                channel.attr(key).set(e.getValue());
            }
        }

        //channel=NioServerSocketChannel
        //获取AbstractChannel.pipeline();的pipeline(DefaultChannelPipeline)
        ChannelPipeline p = channel.pipeline();

        final EventLoopGroup currentChildGroup = childGroup;
        final ChannelHandler currentChildHandler = childHandler;
        final Entry<ChannelOption<?>, Object>[] currentChildOptions;
        final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
        synchronized (childOptions) {
            currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0));
        }
        synchronized (childAttrs) {
            currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0));
        }

        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) throws Exception {
                //System.out.println(ch==channel);   true
                final ChannelPipeline pipeline = ch.pipeline();
                //System.out.println(pipeline==p);  true
                //config.handler()=自己创建的new ChannelInitializer<ServerSocketChannel>()
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    pipeline.addLast(handler);
                }

                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
//                        System.out.println("执行了");
                        //bossGroup将客户端连接转交给workerGroup
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });
            }
        });
    }

主要看 ChannelPipeline p = channel.pipeline();这里的p有值是因为在创建NioServerSocketChannel的构造方法时赋值的.

    protected DefaultChannelPipeline(Channel channel) {
        this.channel = ObjectUtil.checkNotNull(channel, "channel");
        succeededFuture = new SucceededChannelFuture(channel, null);
        voidPromise =  new VoidChannelPromise(channel, true);

        //创建尾结点
        tail = new TailContext(this);
        //创建头节点   头节点中维护了AbstractChannel中unsafe对象
        head = new HeadContext(this);

        head.next = tail;
        tail.prev = head;
    }

可以看出来该实体创建了头尾节点,且是链表的结构;
接下来看addlast()方法跟踪到如下代码;

    @Override
    public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
        //group=null
        //name =null
        //handler=new ChannelInitializer<Channel>
        final AbstractChannelHandlerContext newCtx;
        synchronized (this) {
            //检查添加
            checkMultiplicity(handler);

            //filterName(name, handler)   当我们没有指定名字时  给我们默认生成一个
            //new DefaultChannelHandlerContext()
            newCtx = newContext(group, filterName(name, handler), handler);

            addLast0(newCtx);

            // If the registered is false it means that the channel was not registered on an eventLoop yet.
            // In this case we add the context to the pipeline and add a task that will call
            // ChannelHandler.handlerAdded(...) once the channel is registered.
            if (!registered) {
                //判断handlerState属性等于0  并且设置为1
                newCtx.setAddPending();
                callHandlerCallbackLater(newCtx, true);
                return this;
            }

            //返回NioEvenGroup
            EventExecutor executor = newCtx.executor();
            if (!executor.inEventLoop()) {
                callHandlerAddedInEventLoop(newCtx, executor);
                return this;
            }
        }
        callHandlerAdded0(newCtx);
        return this;
    }

newCtx = newContext(group, filterName(name, handler), handler);完成以下事情:
给DefaultChannelHandlerContext这个类的属性附上值
//此Handler是ChannelInitializer
this.handler = handler;
addLast0(newCtx);这个就是把newCtx 这个链表的节点加入pipeline里的链表属性结构中去这样链表结构如下
head->newctx->tail
tail指向head形成闭环;
接下来走 callHandlerCallbackLater(newCtx, true);
主要是给defultpipeline类的private PendingHandlerCallback pendingHandlerCallbackHead;赋值为new PendingHandlerAddedTask(newCtx);

这个init()方法就结束了接下来继续看
abstractbootStrap的initAndRegister() 方法里的 ChannelFuture regFuture = config().group().register(channel);
跟踪到会到如下:
AbstractChannel的的内部类AbstractUnsafe的register()方法

 @Override
        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;
            }

            //promise=DefaultChannelPromise
            //eventLoop=SingleThreadEventLoop

            //this.eventLoop=NioEventLoop==>SingleThreadEventLoop.this
            AbstractChannel.this.eventLoop = eventLoop;

            //他们最终都调用了register0   eventLoop.inEventLoop()的作用?
            if (eventLoop.inEventLoop()) {
                register0(promise);
            } else {
                try {
                    eventLoop.execute(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("register0");
                            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);
                }
            }
        }

根据逻辑判断接下来会走
eventLoop.execute(new Runnable() {
@Override
public void run() {
System.out.println(“register0”);
register0(promise);
}
});
继续跟踪到
SingleThreadEventExecutor的execute();


    @Override
    public void execute(Runnable task) {
        System.out.println("ccccccccccc");
        if (task == null) {
            throw new NullPointerException("task");
        }

        //调用doStartThread方法启动事件轮询后此方法返回true
        boolean inEventLoop = inEventLoop();
        //将任务加入线程队列
        addTask(task);
        //判断当前执行此任务的线程是否是SingleThreadEventExecutor
        if (!inEventLoop) {
            startThread();
            if (isShutdown()) {
                boolean reject = false;
                try {
                    if (removeTask(task)) {
                        reject = true;
                    }
                } catch (UnsupportedOperationException e) {
                    // The task queue does not support removal so the best thing we can do is to just move on and
                    // hope we will be able to pick-up the task before its completely terminated.
                    // In worst case we will log on termination.
                }
                if (reject) {
                    reject();
                }
            }
        }

        if (!addTaskWakesUp && wakesUpForTask(task)) {
            //唤醒阻塞的selectT
            wakeup(inEventLoop);
        }
    }

其中 addTask(task);该代码是 让
SingleThreadEventExecutor类的属性 private final Queue taskQueue;里加了一个task任务.这个任务就就只有一个方法register0()
然后走 startThread();方法跟踪下去到
SingleThreadEventExecutor的doStartThread()

 private void doStartThread() {
        assert thread == null;
        //真正的启动线程
        executor.execute(new Runnable() {
            @Override
            public void run() {
                //将此线程保存起来
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }

                boolean success = false;
                updateLastExecutionTime();
                try {
                    SingleThreadEventExecutor.this.run();
                    success = true;
                } catch (Throwable t) {
                    logger.warn("Unexpected exception from an event executor: ", t);
                } finally {
                    for (;;) {
                        int oldState = state;
                        if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
                                SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
                            break;
                        }
                    }

                    // Check if confirmShutdown() was called at the end of the loop.
                    if (success && gracefulShutdownStartTime == 0) {
                        if (logger.isErrorEnabled()) {
                            logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
                                    SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must " +
                                    "be called before run() implementation terminates.");
                        }
                    }

                    try {
                        // Run all remaining tasks and shutdown hooks.
                        for (;;) {
                            if (confirmShutdown()) {
                                break;
                            }
                        }
                    } finally {
                        try {
                            cleanup();
                        } finally {
                            // Lets remove all FastThreadLocals for the Thread as we are about to terminate and notify
                            // the future. The user may block on the future and once it unblocks the JVM may terminate
                            // and start unloading classes.
                            // See https://github.com/netty/netty/issues/6596.
                            FastThreadLocal.removeAll();

                            STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                            threadLock.countDown();
                            if (logger.isWarnEnabled() && !taskQueue.isEmpty()) {
                                logger.warn("An event executor terminated with " +
                                        "non-empty task queue (" + taskQueue.size() + ')');
                            }
                            terminationFuture.setSuccess(null);
                        }
                    }
                }
            }
        });
    }

thread = Thread.currentThread();这个代码块赋值thread属性为当前线程,
接着看下面的SingleThreadEventExecutor.this.run();的run()方法跟踪到子类nioeventloop的run方法如下:

//事件循环
    @Override
    protected void run() {
        for (;;) {
            try {
                try {
                    //hasTasks()  若taskQueue or  tailTasks任务队列中有任务  返回false  没有则返回true
//                  //有任务返回selectnow的返回值   没任务返回-1
                    switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                    case SelectStrategy.CONTINUE:
                        continue;

                    case SelectStrategy.BUSY_WAIT:
                        // fall-through to SELECT since the busy-wait is not supported with NIO

                    case SelectStrategy.SELECT:
                        //首先轮询注册到reactor线程对应的selector上的所有的channel的IO事件
                        //wakenUp 表示是否应该唤醒正在阻塞的select操作,netty在每次进行新的loop之前,都会将wakeUp 被设置成false,标志新的一轮loop的开始
                        select(wakenUp.getAndSet(false));

  
                        if (wakenUp.get()) {
                            selector.wakeup();
                        }
                        // fall through
                    default:
                    }
                } catch (IOException e) {
                    // If we receive an IOException here its because the Selector is messed up. Let's rebuild
                    // the selector and retry. https://github.com/netty/netty/issues/8566
                    rebuildSelector0();
                    handleLoopException(e);
                    continue;
                }

                cancelledKeys = 0;
                needsToSelectAgain = false;
                final int ioRatio = this.ioRatio;
                if (ioRatio == 100) {
                    try {
                        processSelectedKeys();
                    } finally {
                        // Ensure we always run tasks.
                        runAllTasks();
                    }
                } else {
                    final long ioStartTime = System.nanoTime();
                    try {
                        //2.处理产生网络IO事件的channel
                        processSelectedKeys();
                    } finally {
                        // Ensure we always run tasks.
                        final long ioTime = System.nanoTime() - ioStartTime;
                        //3.处理任务队列
                        runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
                    }
                }
            } catch (Throwable t) {
                handleLoopException(t);
            }
            // Always handle shutdown even if the loop processing threw an exception.
            try {
                if (isShuttingDown()) {
                    closeAll();
                    if (confirmShutdown()) {
                        return;
                    }
                }
            } catch (Throwable t) {
                handleLoopException(t);
            }
        }
    }

以上代码根据逻辑,因为启动的时候,是没有往selector注册事件所以 switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) 这个结果为0;所以直接往下走到
//2.处理产生网络IO事件的channel
processSelectedKeys();
这个方法主要是处理通道,第一次肯定没有所以跳过到
//3.处理任务队列
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
处理taskqueue里的任务目前这队列只有一个run()就是上面register0()方法,现在开始执行该方法,该方法也是该线程在执行
AbstractChannel类的内部类的AbstractUnsafe方法;如下

private void register0(ChannelPromise promise) {
            try {
                // 检查通道是否仍然打开,因为它可以在寄存器的平均时间内关闭
                // 调用在eventLoop之外

                //promise=DefaultChannelPromise
                if (!promise.setUncancellable() || !ensureOpen(promise)) {
                    return;
                }
                boolean firstRegistration = neverRegistered;
                //调用NioServerSocketChannel 通过反射创建出来nio底层channel的register方法  选择器看不同操作系统
                doRegister();
                neverRegistered = false;
                registered = true;

                // 确保在实际通知承诺之前调用handlerAdded(…)。这是需要的
                // 用户可能已经通过ChannelFutureListener中的管道触发事件。

                //会执行handlerAdded方法
                pipeline.invokeHandlerAddedIfNeeded();

                safeSetSuccess(promise);
                //会执行channelRegistered
                pipeline.fireChannelRegistered();

                // 只有当通道从未被注册时,才激活该通道。这可以防止解雇
                // 如果取消注册并重新注册通道,则多个通道将激活。
                if (isActive()) {
                    if (firstRegistration) {
                        pipeline.fireChannelActive();
                    } else if (config().isAutoRead()) {
                        // 这个通道之前已经注册,并设置了autoRead()。这意味着我们需要开始读取
                        // 这样我们就可以处理入站数据。
                        //
                        // See https://github.com/netty/netty/issues/4805
                        beginRead();
                    }
                }
            } catch (Throwable t) {
                // 直接关闭通道,避免FD泄漏。
                closeForcibly();
                closeFuture.setClosed();
                safeSetFailure(promise, t);
            }
        }

其中的 doRegister();

 //注册核心方法
    @Override
    protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {
                //javaChannel()   ==>  ServerSocketChannel 通过反射创建出来nio底层channel
                //调用Nio底层将ServerSocketChannel注册到selector上
                selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
                return;
            } catch (CancelledKeyException e) {
                if (!selected) {
                    //强制选择器现在选择,因为“已取消”的SelectionKey可能仍然是
                    //缓存并没有删除,因为还没有调用Select.select(..)操作。
                    eventLoop().selectNow();
                    selected = true;
                } else {
                    //我们之前在选择器上强制执行了select操作,但是SelectionKey仍然缓存
                    //不管什么原因。JDK错误?
                    throw e;
                }
            }
        }
    }

是把serversocketchannel注册到netty的替换过的selector上,此时的感兴趣事件没有,且加了附加对象abstractnioChannel;
接下来看
//会执行handlerAdded方法
pipeline.invokeHandlerAddedIfNeeded();
这个方法实际上就是运行了处理链中的中间节点,该节点的属性有个handler值为ChannelInitializer实体上面的代码:
如下

p.addLast(new ChannelInitializer() {
@Override
public void initChannel(final Channel ch) throws Exception {
//System.out.println(chchannel); true
final ChannelPipeline pipeline = ch.pipeline();
//System.out.println(pipeline
p); true
//config.handler()=自己创建的new ChannelInitializer()
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}

            ch.eventLoop().execute(new Runnable() {
                @Override
                public void run() {

// System.out.println(“执行了”);
//bossGroup将客户端连接转交给workerGroup
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
实际运行代码里的initchannel()方法.,其中的 pipeline.addLast(handler);这个handler就是我们开发的那个handler代码上
.handler(new NettyTestHendler())
此时的pipeline的handler;链表是head->newctx->nettyTestHendler->tail
接下来
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
这个又会往pipeline加个节点
此时的pipeline的handler;链表是head->newctx->nettyTestHendler->ServerBootstrapAcceptor-> tail
接下会把newctx给删除
最后服务端的serversocketChannel的pipeline的处理链为
head->nettyTestHendler->ServerBootstrapAcceptor-> tail
这样基本上初始化和注册就好了
总结:initAndRegister();这个方法主要是做了初始化服务端的处理链的构造,以及把通道注册到selector上

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值