netty启动流程(二)

169 阅读6分钟

boosGroup和workerGroup创建完成,接下来就该启动server了。

1、ServerBootstrap#bind

ServerBootstrap#bind(int) 实际调用的是ServerBootstrap继承自父类AbstractBootstrap的方法

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {


    public ChannelFuture bind(int inetPort) {
        //调用下面的重载方法
        return bind(new InetSocketAddress(inetPort));
    }


    public ChannelFuture bind(SocketAddress localAddress) {
        //判断 group channelFactory 对象不为空    serverBootstrap.group    serverBootstrap.channel  已经设置
        validate();
        //ObjectUtil.checkNotNull(localAddress, "localAddress") 还是返回的localAddress对象  判断不为空
        return doBind(ObjectUtil.checkNotNull(localAddress, "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();
            //见netty启动流程(四)
            doBind0(regFuture, channel, localAddress, promise);
            return promise;
        } else {
            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) {
                        promise.setFailure(cause);
                    } else {
                        promise.registered();
                        //见netty启动流程(四)
                        doBind0(regFuture, channel, localAddress, promise);
                    }
                }
            });
            return promise;
        }
    }
}

initAndRegister()初始化和注册

初始化流程:
1、工厂创建服务端channel,即通过反射创建NioServerSocketChannel
2、初始化


AbstractBootstrap.initAndRegister

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
    
    final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            //bootstrap.channel(NioServerSocketChannel.class)
            //通过反射创建NioServerSocketChannel  注意NioServerSocketChannel的构造方法
            //channelFactory=new ReflectiveChannelFactory  ---> constructor=NioServerSocketChannel.class.getConstructor();
            //channel=NioServerSocketChannel
            //ReflectiveChannelFactory
            //2 创建服务端channel
            channel = channelFactory.newChannel();//==>关注NioServerSocketChannel
            //3 初始化
            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
        //MultithreadEventLoopGroup.register()
        //在下篇文章中介绍
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }
        return regFuture;
    }
}

2 创建服务端Channel

ReflectiveChannelFactory#newChannel,通过工厂创建服务端channel

创建NioServerSocketChannel的流程:
1、创建Unsage对象,netty的读写数据都是通过该对象实现的
2、创建pipeline
3、保存Java原生的Channel
NioServerSocketChannel -> ServerSocketChannel
NioSocketChannel -> SocketChannel
4、设置感兴趣的事件
NioServerSocketChannel -> OP_ACCEPT
NioSocketChannel -> OP_READ
5、设置ServerSocketChannel为非阻塞
public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> {

    public T newChannel() {
        try {
            // T=NioServerSocketChannel   constructor=NioServerSocketChannel.class.getConstructor();
            return constructor.newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
        }
    }
}

接下里看NioServerSocketChannel的创建流程

public class NioServerSocketChannel extends AbstractNioMessageChannel
                             implements io.netty.channel.socket.ServerSocketChannel {
  

    /**
     * 创建一个新实例
     * 反射创建NioServerSocketChannel调用
     */
    public NioServerSocketChannel() {
        //newSocket(DEFAULT_SELECTOR_PROVIDER)返回 ServerSocketChannel
        //调用下面的构造方法
        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
    }
    
     public NioServerSocketChannel(ServerSocketChannel channel) {
         //父类构造器
        super(null, channel, SelectionKey.OP_ACCEPT);
        //javaChannel()==>  serverSocketChannel
        config = new NioServerSocketChannelConfig(this, javaChannel().socket());
    }


    private static ServerSocketChannel newSocket(SelectorProvider provider) {
        try {
            /**
             *  使用{@link SelectorProvider}打开{@link SocketChannel},从而删除条件in
             *  否则,每个ServerSocketChannel.open()将调用{@link SelectorProvider#provider()}。
             *
             *  See <a href="https://github.com/netty/netty/issues/2308">#2308</a>.
             */
            return provider.openServerSocketChannel();
        } catch (IOException e) {
            throw new ChannelException(
                    "Failed to open a server socket.", e);
        }
    }                 
}

AbstractNioMessageChannel

public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
   
    protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        //parent -->  null
        //ch--> serverSocketChannel  服务端channel
        //readInterestOp--->SelectionKey.OP_ACCEPT
        super(parent, ch, readInterestOp);
    }
    
    //重写了AbstractChannel的方法
    protected AbstractNioUnsafe newUnsafe() {
        return new NioMessageUnsafe();
    }


}

AbstractNioChannel

public abstract class AbstractNioChannel extends AbstractChannel {
    
    protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        //parent -->  null
        //ch--> serverSocketChannel  服务器channel
        //readInterestOp--->SelectionKey.OP_ACCEPT

        //创建id,unsafe pipeline(创建头尾节点)
        super(parent);
        /**
         * NioServerSocketChannel -> ServerSocketChannel
         * NioSocketChannel -> SocketChannel
         */
        this.ch = ch;

        /**
         * NioServerSocketChannel -> OP_ACCEPT
         * NioSocketChannel -> OP_READ
         */
        this.readInterestOp = readInterestOp;
        try {
            //设置非阻塞
            ch.configureBlocking(false);
        } catch (IOException e) {
            try {
                ch.close();
            } catch (IOException e2) {
                if (logger.isWarnEnabled()) {
                    logger.warn(
                            "Failed to close a partially initialized socket.", e2);
                }
            }

            throw new ChannelException("Failed to enter non-blocking mode.", e);
        }
    }
}

AbstractChannel

public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {

    protected AbstractChannel(Channel parent) {
        //new ServerSocketChannel
        this.parent = parent;
        id = newId();
        //NioServerSocketChannel -> AbstractNioMessageChannel.newUnsafe 读写都由unsafe完成
        //NioSocketChannel ->  AbstractNioByteChannel.newUnsafe
        unsafe = newUnsafe();
        //创建pipeline 并初始化
        pipeline = newChannelPipeline();
    }
    

    protected DefaultChannelPipeline newChannelPipeline() {
        //创建pipeline  初始化pipeline
        return new DefaultChannelPipeline(this);
    }
}

2.1 创建unsafe

public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
 
    protected AbstractNioUnsafe newUnsafe() {
        return new NioMessageUnsafe();
    }


}

2.2创建pipeline

pipeline的创建流程:
1、ChannelPipeline 中维护了一个有头尾节点,由ChannelHandlerContext 组成的双向链表。
头是HeadContext,链表的尾是TailContext,并且每个ChannelHandlerContext 中又关联着一个ChannelHandler。
2、创建头尾节点的时候会初始化一个计算ChannelHandler类型的蒙版。ChannelHandler大致上可以分为Inbound和OutboundHandler,前者处理入栈事件,后者处理出栈事件,通过蒙版,可以高效的通过与操作计算ChannelHandler的类型

pipeline.webp

有头尾节点的管道

public class DefaultChannelPipeline implements ChannelPipeline {

    final AbstractChannelHandlerContext head;
    final AbstractChannelHandlerContext tail;

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

        //头尾节点没有ChannelHandler
        //创建尾结点
        tail = new TailContext(this);
        //创建头节点   头节点中维护了AbstractChannel中unsafe对象
        head = new HeadContext(this);
        
        //构造管道
        head.next = tail;
        tail.prev = head;
    }
}

接下来看头尾节点的创建流程

2.2.1 创建尾结点

TailContext

final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler {

    TailContext(DefaultChannelPipeline pipeline) {
        super(pipeline, null, TAIL_NAME, TailContext.class);
        setAddComplete();
    }
}

2.2.2 创建头结点

HeadContext

final class HeadContext extends AbstractChannelHandlerContext
        implements ChannelOutboundHandler, ChannelInboundHandler {
    private final Unsafe unsafe;
    HeadContext(DefaultChannelPipeline pipeline) {
        super(pipeline, null, HEAD_NAME, HeadContext.class);
        unsafe = pipeline.channel().unsafe();
        setAddComplete();
    }
}

HeadContext和TailContext的共同父类:AbstractChannelHandlerContext

abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
 
    AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,
                                  String name, Class<? extends ChannelHandler> handlerClass) {
        //pipeline=DefaultChannelPipeline
        //executor=null
        //name =没传系统默认创建
        //handler=TailContext.class
        this.name = ObjectUtil.checkNotNull(name, "name");
        this.pipeline = pipeline;
        this.executor = executor;
        /**
         * 计算ChannelHandler的蒙版
         *  根据这个类创建一个mask
         *  mask:
         *  1、可以标识当前ChannelHandler的类型 Inboud ? OutBound
         *  2、结合 @Skip注解 判断当前ChannelHandler的某些方法在pipeline的传播过程中是否需要跳过
         *      因为可能某个方法的默认实现没有业务逻辑代码 只是起到向下传递的作用
         */
        this.executionMask = mask(handlerClass);
        // Its ordered if its driven by the EventLoop or the given Executor is an instanceof OrderedEventExecutor.
        ordered = executor == null || executor instanceof OrderedEventExecutor;
    }

}
final class ChannelHandlerMask {
 
    static int mask(Class<? extends ChannelHandler> clazz) {
        // Try to obtain the mask from the cache first. If this fails calculate it and put it in the cache for fast
        // lookup in the future.
        Map<Class<? extends ChannelHandler>, Integer> cache = MASKS.get();
        Integer mask = cache.get(clazz);
        if (mask == null) {
            /**
             * 计算mask值
             * 1、Inboud or OutBound
             * 2、结合@Skip判断某些方法在pipeline的事件传播过程中是否需要跳过
             */
            mask = mask0(clazz);
            cache.put(clazz, mask);
        }
        return mask;
    }
}

3 初始化

初始化流程:
1、赋值用户设置的参数
2、向pipeline中添加一个ChannelInitializer类型的ChannelHandler,在服务器启动过程中会执行一次,执行完后就会从pipeline中移除。这个ChannelInitializer向pipeline中添加了一个非常重要的ChannelHandler-用来接受客户端连接的ServerBootstrapAcceptor。
注意:这个ChannelInitializer只是添加到了pipeline中,现在还不会执行。

public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
    
    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));
        }

        /** 添加完成后
         * pipeline head -> ChannelInitializer -> tail
         */
        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()=调用ServerBootstrap.handler(Handler)传入的handler
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    pipeline.addLast(handler);
                }

                //添加到任务队列 不会立即执行 由nioEventLoop绑定的线程执行到处理任务队列 时才会执行
                //SingleThreadEventExecutor.execute
                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
//                        System.out.println("执行了");
                        //bossGroup将客户端连接转交给workerGroup
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                    //执行完成后  pipeline head- > ChannelInitializer(马上会从pipeline移除掉) -> NettyTestHandler-> ServerBootstrapAcceptor -> tail
                });
            }
        });


//       p.addLast(new ChannelInitializer<Channel>() {
//           @Override
//           protected void initChannel(Channel ch) throws Exception {
//               System.out.println("hahahah");
//           }
//       });

    }
}