netty初探ServerBootstrap主要类和起动流程

几个关键类:

1.NioServerSocketChannel

netty初探ServerBootstrap主要类和起动流程_第1张图片

 

2.NioSocketChannel

netty初探ServerBootstrap主要类和起动流程_第2张图片

两个继承和实现的接口都差不多,功能也差不多

3.ServerBootstrap 和 Bootstrap都继承自AbstractBootstrap功能都是作为入口,构建服务端和客户端

4.NioEventLoopGroup

netty初探ServerBootstrap主要类和起动流程_第3张图片

5.NioEventLoop

netty初探ServerBootstrap主要类和起动流程_第4张图片

6.DefaultChannelPipeline

netty初探ServerBootstrap主要类和起动流程_第5张图片

 

二.初始化流程

创建一个服务端代码

EventLoopGroup bossgroup = new NioEventLoopGroup();
EventLoopGroup workgroup = new NioEventLoopGroup();
try{
    ServerBootstrap b = new ServerBootstrap();
    b.group(bossgroup,workgroup)
     .channel(NioServerSocketChannel.class)
     .option(ChannelOption.SO_BACKLOG,100)
     .handler(new LoggingHandler(LogLevel.INFO))
     .childHandler(new ChannelInitializer() {

        @Override
        public void initChannel(SocketChannel socketChannel) throws Exception {
            socketChannel.pipeline().addLast(new ProtobufVarint32FrameDecoder());
            socketChannel.pipeline().addLast(new                                 
                   ProtobufDecoder(SubscribeReqProto.SubscribeReq.getDefaultInstance()));

            socketChannel.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
            socketChannel.pipeline().addLast(new ProtobufEncoder());
            socketChannel.pipeline().addLast(new SubReqHandler());

        }
     });

    ChannelFuture f = b.bind(port).sync();
    f.channel().closeFuture().sync();
}finally {
    bossgroup.shutdownGracefully();
    workgroup.shutdownGracefully();
}

group()、channel()、option() 、handler() 、childHandler()都是配置属性信息

整个创建初始化注册是在bind()方法内


public ChannelFuture bind(int inetPort) {
    return bind(new InetSocketAddress(inetPort));
}

public ChannelFuture bind(SocketAddress localAddress) {
    validate();
    if (localAddress == null) {
        throw new NullPointerException("localAddress");
    }
    return doBind(localAddress);
}

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

再看一下initAndRegister() 主要是创建server channel和注册selector

final ChannelFuture initAndRegister() {

    Channel channel = null;

    try {
        //创建channel对象
        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 GlobalEventExecutor
        return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
    }

    //注册channel到selector上
    ChannelFuture regFuture = config().group().register(channel);

    if (regFuture.cause() != null) {
        if (channel.isRegistered()) {
            channel.close();
        } else {
            channel.unsafe().closeForcibly();
        }
    }

    // If we are here and the promise is not failed, it's one of the following cases:
    // 1) If we attempted registration from the event loop, the registration has been     completed at this point.
    // i.e. It's safe to attempt bind() or connect() now because the channel has been registered.
    // 2) If we attempted registration from the other thread, the registration request has been successfully
    // added to the event loop's task queue for later execution.
    // i.e. It's safe to attempt bind() or connect() now:
    // because bind() or connect() will be executed *after* the scheduled registration task is executed
    // because register(), bind(), and connect() are all bound to the same thread.
    return regFuture;
}

 

channelFactory 是在调用channel()方法时初始化的

public B channel(Class channelClass) {

    if (channelClass == null) {
        throw new NullPointerException("channelClass");
    }
    return channelFactory(new ReflectiveChannelFactory(channelClass));
}

public B channelFactory(io.netty.channel.ChannelFactory channelFactory) {
    return channelFactory((ChannelFactory) channelFactory);
}

public B channelFactory(ChannelFactory channelFactory) {

    if (channelFactory == null) {
        throw new NullPointerException("channelFactory");
    }

    if (this.channelFactory != null) {
        throw new IllegalStateException("channelFactory set already");
    }

    this.channelFactory = channelFactory;
    return self();
}

channelFactory.newChannel(); 根据传入的具体类名来实例化channel对象,比较常见的是NioServerSocketChannel,下面具体看一下NioServerSocketChannel对象初始化过程

private static ServerSocketChannel newSocket(SelectorProvider provider) {

    try {
        /**
        * Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
        * {@link SelectorProvider#provider()} which is called by each     ServerSocketChannel.open() otherwise.
        *
        * See #2308.
        */
        return provider.openServerSocketChannel();
    } catch (IOException e) {
        throw new ChannelException("Failed to open a server socket.", e);
    }
}

public NioServerSocketChannel() {
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}

provider对象是通过java SelectorProvider 的provider方法来创建

public static SelectorProvider provider() {

    synchronized (lock) {

        if (provider != null)
            return provider;

        return AccessController.doPrivileged(
                    new PrivilegedAction() {

                          public SelectorProvider run() {

                                if (loadProviderFromProperty())
                                    return provider;

                                if (loadProviderAsService())
                                    return provider;

                                provider = sun.nio.ch.DefaultSelectorProvider.create();
                                return provider;
                          }
                    });
    }
}

pipeline是在NioServerSocketChannel 父类AbstractChannel的构造函数中创建的

protected AbstractChannel(Channel parent) {
    this.parent = parent;
    id = newId();
    unsafe = newUnsafe();
    pipeline = newChannelPipeline();
}

protected DefaultChannelPipeline newChannelPipeline() {
    return new DefaultChannelPipeline(this);
}

创建完channel之后要对channel进行一些配置,init(channel)方法是在子类ServerBootstrap中

void init(Channel channel) throws Exception {

    final Map, Object> options = options0();
    synchronized (options) {
        setChannelOptions(channel, options, logger);
    }

    final Map, Object> attrs = attrs0();
    synchronized (attrs) {
        for (Entry, Object> e: attrs.entrySet()) {
            @SuppressWarnings("unchecked")
            AttributeKey key = (AttributeKey) e.getKey();
            channel.attr(key).set(e.getValue());
        }
    }

    ChannelPipeline p = channel.pipeline();
    final EventLoopGroup currentChildGroup = childGroup;
    final ChannelHandler currentChildHandler = childHandler;
    final Entry, Object>[] currentChildOptions;
    final Entry, Object>[] currentChildAttrs;

    synchronized (childOptions) {
        currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size()));
    }

    synchronized (childAttrs) {
        currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size()));
    }

    //添加一个channelInitializer handler
    p.addLast(new ChannelInitializer() {

        @Override
        public void initChannel(final Channel ch) throws Exception {

            final ChannelPipeline pipeline = ch.pipeline();
            ChannelHandler handler = config.handler();
            if (handler != null) {
                pipeline.addLast(handler);
            }

            ch.eventLoop().execute(new Runnable() {
                @Override
                public void run() {
                    pipeline.addLast(new ServerBootstrapAcceptor(
                    ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                }
            });
        }
    });
} 
  

到此init的整个过程完成,构建完成以后需要把channel绑到selector上,实现跟java nio的过程一样

注册是在NioEventLoopGroup的父类MultithreadEventLoopGroup中

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

@Override
public EventLoop next() {
    return (EventLoop) super.next();
}

返回的是一个EventLoop,接着看NioEventLoop中的注册方法

注册channel是在NioEventLoop父类SingleThreadEventLoop中

@Override
public ChannelFuture register(Channel channel) {
    return register(new DefaultChannelPromise(channel, this));
}

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

又返回到channel中,看channel是怎么处理的

AbstractChannel中

@Override
public Unsafe unsafe() {
    return unsafe;
}

这个unsafe是之前实例化channel对象的时候通过newUnfase()创建的

AbstractNioMessageChannel类中

@Override
protected AbstractNioUnsafe newUnsafe() {
    return new NioMessageUnsafe();
}

接下来看一个NioMessageUnsafe怎么注册的

方法在父类AbstractUnsafe中

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

}


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;

        // Ensure we call handlerAdded(...) before we actually notify the promise. This is needed as the
        // user may already fire events through the pipeline in the ChannelFutureListener.
        //通知pipeline调用handler添加事件
        pipeline.invokeHandlerAddedIfNeeded();

        safeSetSuccess(promise);
        pipeline.fireChannelRegistered();
        // Only fire a channelActive if the channel has never been registered. This prevents firing
        // multiple channel actives if the channel is deregistered and re-registered.
        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);
    }
}

AbstractNioChannel类中

@Override
protected void doRegister() throws Exception {

    boolean selected = false;
    for (;;) {
        try {
            //注册OP_CONNECT事件
            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;
            }
       }
    }
}

回到DefaultChannelPipeline中看一下invokeHandlerAddedIfNeeded

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

    // 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;
    while (task != null) {
        task.execute();
        task = task.next;
    }
}

从head开始执行pipeline中的task

private final class PendingHandlerAddedTask extends PendingHandlerCallback {

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

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

    @Override
    void execute() {
        EventExecutor executor = ctx.executor();

        if (executor.inEventLoop()) {
            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);
                }
                remove0(ctx);
                ctx.setRemoved();
            }
        }
    }
}

callHandlerAdded0 

private void callHandlerAdded0(final AbstractChannelHandlerContext ctx) {
    try {
        ctx.handler().handlerAdded(ctx);
        ctx.setAddComplete();
    } catch (Throwable t) {
        boolean removed = false;
        try {
            remove0(ctx);
            try {
                ctx.handler().handlerRemoved(ctx);
            } finally {
                ctx.setRemoved();
            }
            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));
        }
    }
}

执行ChannelHandler 的handlerAdded方法,

handler是在执行ServerBootstrap init()时添加的

    @Override
    void init(Channel channel) throws Exception {
        final Map, Object> options = options0();
        synchronized (options) {
            setChannelOptions(channel, options, logger);
        }

        final Map, Object> attrs = attrs0();
        synchronized (attrs) {
            for (Entry, Object> e: attrs.entrySet()) {
                @SuppressWarnings("unchecked")
                AttributeKey key = (AttributeKey) e.getKey();
                channel.attr(key).set(e.getValue());
            }
        }

        ChannelPipeline p = channel.pipeline();

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

        //添加handler
        p.addLast(new ChannelInitializer() {
            @Override
            public void initChannel(final Channel ch) throws Exception {
                final ChannelPipeline pipeline = ch.pipeline();
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    pipeline.addLast(handler);
                }

                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });
            }
        });
    } 
  

看一下ChannelInitializer中的handlerAdded方法

     /**
     * {@inheritDoc} If override this method ensure you call super!
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        if (ctx.channel().isRegistered()) {
            // This should always be true with our current DefaultChannelPipeline implementation.
            // The good thing about calling initChannel(...) in handlerAdded(...) is that there will be no ordering
            // surprises if a ChannelInitializer will add another ChannelInitializer. This is as all handlers
            // will be added in the expected order.
            initChannel(ctx);
        }
    }

最后调用到ChannelInitializer的initChannel方法,但是这个InitChannel的方法在ServerBootstrap init()方法添加handler时被重写了,主要作用是把config对象中的handler添加到pipeline,其实就是ServerBootstrap.handler()方法绑定的handler.

.handler(new LoggingHandler(LogLevel.INFO))这种方式添加的handler,最后添加一个ServerBootstrapAcceptor handler

执行完invokeHandlerAddedIfNeeded后开始执行pipeline.fireChannelRegistered();

DefaultChannelPipeline

@Override
public final ChannelPipeline fireChannelRegistered() {
    AbstractChannelHandlerContext.invokeChannelRegistered(head);
    return this;
}
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 {
            ((ChannelInboundHandler) handler()).channelRegistered(this);
        } catch (Throwable t) {
            notifyHandlerException(t);
        }
    } else {
        fireChannelRegistered();
    }
}

依次执行pipeline中的handler的channelRegistered

到此server端的起动流程就结束了

 

你可能感兴趣的:(java,opendaylight)