Netty ServerBootstrap bind和acceptor 事件源代码剖析




流程1 :在ServerBootstrap(AbstractBootstrap<B,C>).bind(int) 绑定端口。


1、ServerBootstrap(AbstractBootstrap<B,C>).initAndRegister()   创建一个ServerSocketChannel ,并注册到EventLoop中。

 在init时,主要通过工厂方法创建一个ServerSocketChannel ,并初始化。ServerBootstrap.init(Channel) 


         在init方法里面主要在PipeLine中增加了一个ServerBootstrapAcceptor ,用来处理新连接。


2、 NioEventLoopGroup(MultithreadEventLoopGroup).register(Channel)  把ServerSocketChannel注册到EventLoop 中,并返回一个ChannelFuture .


EventLoop 与ServerSocketChannel  的关系主要由io.netty.util.concurrent.EventExecutorChooserFactory 类来决定。



当EventLoop与ServerSocketChannel关联建立之后。实际执行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;
            }

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


此时,为main线程调用register方法,所以通过eventLoop 来执行register任务。


  eventLoop.execute(new Runnable() {
                        @Override
                        public void run() {
                            register0(promise);
                        }
                    });

实际注册ServerSocketChannel的堆栈如下:


ServerBootstrap$1.initChannel(Channel) line: 172
ServerBootstrap$1(ChannelInitializer<C>).initChannel(ChannelHandlerContext) line: 113
ServerBootstrap$1(ChannelInitializer<C>).handlerAdded(ChannelHandlerContext) line: 105
DefaultChannelPipeline.callHandlerAdded0(AbstractChannelHandlerContext) line: 597
DefaultChannelPipeline.access$000(DefaultChannelPipeline, AbstractChannelHandlerContext) line: 44
DefaultChannelPipeline$PendingHandlerAddedTask.execute() line: 1387
DefaultChannelPipeline.callHandlerAddedForAllHandlers() line: 1122
DefaultChannelPipeline.invokeHandlerAddedIfNeeded() line: 647
AbstractNioMessageChannel$NioMessageUnsafe(AbstractChannel$AbstractUnsafe).register0(ChannelPromise) line: 506
AbstractChannel$AbstractUnsafe.access$200(AbstractChannel$AbstractUnsafe, ChannelPromise) line: 419
AbstractChannel$AbstractUnsafe$1.run() line: 478


会执行ServerBootstrap$1.initChannel(Channel) 方法添加ServerBootstrapAcceptor 。


流程2:   EventLoop.run() 线程执行select()方法,等待新链接的到来。


SelectedSelectionKeySetSelector.select(long) line: 62
NioEventLoop.select(boolean) line: 752
NioEventLoop.run() line: 408
SingleThreadEventExecutor$5.run() line: 858
DefaultThreadFactory$DefaultRunnableDecorator.run() line: 138


流程3:  EventLoop.run()  执行select()时,遇到accept事件,调用ServerBootstrapAcceptor.read()事件。


ServerBootstrap$ServerBootstrapAcceptor.channelRead(ChannelHandlerContext, Object) line: 244
DefaultChannelHandlerContext(AbstractChannelHandlerContext).invokeChannelRead(Object) line: 362
AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object) line: 348
DefaultChannelHandlerContext(AbstractChannelHandlerContext).fireChannelRead(Object) line: 340
LoggingHandler.channelRead(ChannelHandlerContext, Object) line: 241
DefaultChannelHandlerContext(AbstractChannelHandlerContext).invokeChannelRead(Object) line: 362
AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object) line: 348
DefaultChannelPipeline$HeadContext(AbstractChannelHandlerContext).fireChannelRead(Object) line: 340
DefaultChannelPipeline$HeadContext.channelRead(ChannelHandlerContext, Object) line: 1334
DefaultChannelPipeline$HeadContext(AbstractChannelHandlerContext).invokeChannelRead(Object) line: 362
AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object) line: 348
DefaultChannelPipeline.fireChannelRead(Object) line: 926
AbstractNioMessageChannel$NioMessageUnsafe.read() line: 93
NioEventLoop.processSelectedKey(SelectionKey, AbstractNioChannel) line: 644
NioEventLoop.processSelectedKeysOptimized() line: 579
NioEventLoop.processSelectedKeys() line: 496
NioEventLoop.run() line: 458
SingleThreadEventExecutor$5.run() line: 858
DefaultThreadFactory$DefaultRunnableDecorator.run() line: 138
FastThreadLocalThread(Thread).run() line: 745


ServerBootstrapAcceptor 事件,主要做一件事件,那就是把childGroup 和SocketChannel 相关联。 之后,读取写入数据就交由EventLoop来处理。


        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            final Channel child = (Channel) msg;

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


在EventLoop  调用select方法时,


   // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
            // to a spin loop
            if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
                unsafe.read();
            }

   @Override
    protected int doReadMessages(List<Object> buf) throws Exception {
        SocketChannel ch = SocketUtils.accept(javaChannel());

        try {
            if (ch != null) {
                buf.add(new NioSocketChannel(this, ch));
                return 1;
            }
        } catch (Throwable t) {
            logger.warn("Failed to create a new channel from an accepted socket.", t);

            try {
                ch.close();
            } catch (Throwable t2) {
                logger.warn("Failed to close a socket.", t2);
            }
        }

        return 0;
    }


List<Object> buf   为缓冲区,但是添加了NioSocketChannel.



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值