启动流程

       服务端启动流程概览:

  • 创建 ServerBootStrap启动类
  • 设置并绑定 NioEventLoopGroup线程池
  • 创建服务端 Channel
  • 添加并设置 ChannelHandler
  • 绑定并启动监听端口

Channel的创建和初始化过程

      Netty服务端的Channel类型是 NioServerSocketChannel,NioServerSocketChannel的创建实际上是从 ServerBootStrapbind()方法开始的,bind()调用doBind()

    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 {
...

        一个 initAndRegister()方法,这个方法就负责 NioServerSocketChannel的初始化和注册操作

final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            channel = channelFactory.newChannel();
            init(channel);
        } catch (Throwable t) {
            if (channel != null) {
                channel.unsafe().closeForcibly();
                return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
            }
            return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
        }

        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }
        return regFuture;
    }

      源码里是调用 channelFactory.newChannel()来创建 channel,创建 Channel的是ReflectiveChannelFactory类,它是ChannelFactory的一个重要实现类

public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> {

    private final Class<? extends T> clazz;

    public ReflectiveChannelFactory(Class<? extends T> clazz) {
        if (clazz == null) {
            throw new NullPointerException("clazz");
        }
        this.clazz = clazz;
    }

    @Override
    public T newChannel() {
        try {
            return clazz.getConstructor().newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + clazz, t);
        }
    }

    @Override
    public String toString() {
        return StringUtil.simpleClassName(clazz) + ".class";
    }
}
  • ServerBootstrap中的ChannelFactory的实现是 ReflectiveChannelFactory
  • 生成的 Channel的具体类型是 NioServerSocketChannel
  • Channel的实例化过程其实就是调用 ChannelFactory.newChannel方法,实际上是通过反射方式进行创建的

NioServerSocketChanel的实例化过程

    private static ServerSocketChannel newSocket(SelectorProvider provider) {
        try {
            return provider.openServerSocketChannel();
        } catch (IOException e) {
            throw new ChannelException("Failed to open a server socket.", e);
        }
    }
    public NioServerSocketChannel() {
        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
    }

       方法newSocket利用 provider.openServerSocketChannel()生成Nio中的 ServerSocketChannel对象,然后调用重载的构造器:

    public NioServerSocketChannel(ServerSocketChannel channel) {
        super(null, channel, SelectionKey.OP_ACCEPT);
        config = new NioServerSocketChannelConfig(this, javaChannel().socket());
    }

       调用父类的构造器,传入的参数是 SelectionKey.OP_ACCEPT

    protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        super(parent, ch, readInterestOp);
    }

--------------父类------------------------
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        super(parent);
        this.ch = ch;
        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);
        }
    }

       设置当前 ServerSocketChannel为非阻塞通道,然后再次进入父类构造器 AbstractChannel(Channel parent):

    protected AbstractChannel(Channel parent) {
        this.parent = parent;
        id = newId();
        unsafe = newUnsafe();
        pipeline = newChannelPipeline();
    }
  • parent属性设置为null
  • 初始化unsafe,用来负责底层的connect,register,read和write操作
  • 初始化pipeline,在实例化一个Channel的同时,当有事件发生的时候,pipeline负责调用相应的Handler进行处理

        unsafe实际是封装了 Java 底层 Socket的操作,因此是沟通 Netty上层和Java 底层重要的桥梁。

ChannelPipeline的初始化

        每个Channel都有对应的 ChannelPipeline,当一个Channel被创建时,对应的ChannelPipeline也会自动创建

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

...

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

  pipeline最终被初始化为一个 DefaultChannelPipelineDefaultChannelPipelineChannelPipeline的实现类,进入它的构造方法

NioEventLoopGroup

        Netty服务端代码中初始化了两个 NioEventLoopGroup,即一个处理客户端连接请求的线程池——bossGroup,一个处理客户端读写操作的线程池——workerGroup,NioEventLoopGroup实现了 Executor接口,Executor框架可以用来创建线程池的,也是一个线程执行器.构造函数最终调用父类MultithreadEventLoopGroup的构造器

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        if (nThreads <= 0) {
            throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
        }

        if (executor == null) {
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }

        children = new EventExecutor[nThreads];

        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
                children[i] = newChild(executor, args);
                success = true;
            } catch (Exception e) {
                // TODO: Think about if this is a good exception type
                throw new IllegalStateException("failed to create a child event loop", e);
            } finally {
                if (!success) {
                    for (int j = 0; j < i; j ++) {
                        children[j].shutdownGracefully();
                    }

                    for (int j = 0; j < i; j ++) {
                        EventExecutor e = children[j];
                        try {
                            while (!e.isTerminated()) {
                                e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
                            }
                        } catch (InterruptedException interrupted) {
                            // Let the caller handle the interruption.
                            Thread.currentThread().interrupt();
                            break;
                        }
                    }
                }
            }
        }

        chooser = chooserFactory.newChooser(children);

        final FutureListener<Object> terminationListener = new FutureListener<Object>() {
            @Override
            public void operationComplete(Future<Object> future) throws Exception {
                if (terminatedChildren.incrementAndGet() == children.length) {
                    terminationFuture.setSuccess(null);
                }
            }
        };

        for (EventExecutor e: children) {
            e.terminationFuture().addListener(terminationListener);
        }

        Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
        Collections.addAll(childrenSet, children);
        readonlyChildren = Collections.unmodifiableSet(childrenSet);
    }

  MultithreadEventExecutorGroup管理着 eventLoop的生命周期,变量:

  • children: EventExecutor数组,保存eventloop
  • chooser: 线程选择器,从children中选取一个 eventloop的策略

  MultithreadEventExecutorGroup的构造器主要分为以下几个步骤:

  • 创建线程执行器——ThreadPerTaskExecutor
  • 调用 newChild方法初始化 children数组
  • 创建线程选择器——chooser

创建ThreadPerTaskExecutor

       开始初始化 NioEventLoopGroup,并没有传入 Executor参数:

public NioEventLoopGroup(int nThreads) {
    this(nThreads, (Executor) null);
}

        到父类MultithreadEventExecutorGroup构造器时,executor 为null, 然后执行:

        if (executor == null) {
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }

       hreadPerTaskExecutor是一个线程执行器,它实现了 Executor接口

public final class ThreadPerTaskExecutor implements Executor {
    private final ThreadFactory threadFactory;

    public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
        if (threadFactory == null) {
            throw new NullPointerException("threadFactory");
        }
        this.threadFactory = threadFactory;
    }

    @Override
    public void execute(Runnable command) {
        threadFactory.newThread(command).start();
    }
}

      ThreadPerTaskExecutor 实现了 execute方法,每次通过调用execute方法执行线程任务

调用 newChild 方法初始化 children 数组

 children[i] = newChild(executor, args);

        通过 newChild方法初始化 EventExecutor数组的每个元素,而 newChild方法如下:

    protected EventLoop newChild(Executor executor, Object... args) throws Exception {
        return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
    }

  每次循环通过newChild实例化一个NioEventLoop对象。

NioEventLoop的初始化

    NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
        if (selectorProvider == null) {
            throw new NullPointerException("selectorProvider");
        }
        if (strategy == null) {
            throw new NullPointerException("selectStrategy");
        }
        provider = selectorProvider;
        final SelectorTuple selectorTuple = openSelector();
        selector = selectorTuple.selector;
        unwrappedSelector = selectorTuple.unwrappedSelector;
        selectStrategy = strategy;
    }

创建线程选择器——chooser

    public EventExecutorChooser newChooser(EventExecutor[] executors) {
        if (isPowerOfTwo(executors.length)) {
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {
            return new GenericEventExecutorChooser(executors);
        }
    }

Channel的注册过程

  Channel的创建和初始化过程,是在 initAndRegister方法中进行的,这个方法里还会将初始化好的 channel注册到 EventLoop线程中去

final ChannelFuture initAndRegister() {
    Channel channel = null;
    try {
        channel = channelFactory.newChannel();
        init(channel);
    } catch (Throwable t) {
       .....
    }

    ChannelFuture regFuture = config().group().register(channel);
    ......
}

          调用config().group().register方法将 channel注册到 EventLoopGroup中去,其目的就是为了实现NIO中把ServerSocketChannel注册到 Selector中去,这样就是可以实现client请求的监听

public ChannelFuture register(Channel channel) {
    return next().register(channel);
}
......
public EventLoop next() {
    return (EventLoop) super.next();
}

  父类MultithreadEventExecutorGroup的next()方法,next方法使用 chooser策略从 EventExecutor[]数组中选择一个 SingleThreadEventLoop

public EventExecutor next() {
    return chooser.next();
}
.....
public EventExecutor next() {
    return executors[idx.getAndIncrement() & executors.length - 1];
}

      再执行 SingleThreadEventLoop的 register()注册方法:

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

     调用了 unsafe的register方法,具体是AbstractUnsafe.register,而unsafe主要用于实现底层的 rergister,read,write等操作。该register方法是:

public final void register(EventLoop eventLoop, final ChannelPromise promise) {
        ......
        AbstractChannel.this.eventLoop = eventLoop;

        if (eventLoop.inEventLoop()) {
            register0(promise);
        } else {
            ......
        }
    }

      将 eventLoop 赋值给 Channel 的 eventLoop 属性,然后又调用了 register0()方法

private void register0(ChannelPromise promise) {
        try {
            ......
            boolean firstRegistration = neverRegistered;
            doRegister();
            neverRegistered = false;
            registered = true;
            pipeline.invokeHandlerAddedIfNeeded();
            safeSetSuccess(promise);
            pipeline.fireChannelRegistered();
            if (isActive()) {
                if (firstRegistration) {
                    pipeline.fireChannelActive();
                } else if (config().isAutoRead()) {
                    beginRead();
                }
            }
        } catch (Throwable t) {
            ......
        }
    }

  doRegister才是最终Nio的注册方法:

protected void doRegister() throws Exception {
    boolean selected = false;
    for (;;) {
        try {
            selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
            return;
        } catch (CancelledKeyException e) {
            if (!selected) {
                eventLoop().selectNow();
                selected = true;
            } else {
                throw e;
            }
        }
    }
}

       通过javaChannel().register(eventLoop().unwrappedSelector(), 0, this)将 Channel对应的Java NIO ServerSocketChannel注册到 EventLoop中的Selector上,最终完成了channel向eventLoop的注册过程。

添加 ChannelHandler

  initAndRegister()方法里,里面有个 init()方法,如下:

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

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

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

       pipeline的 addLast方法,该方法就是添加用于处理出站和入站数据流的 ChannelHandler,而pipeline是从 channel中获取的,之前分析过当创建channel时会自动创建一个对应的 channelPipeline

  serverbootstrap.handler()设置的handler在初始化就会执行,而 serverbootstrap.childHandler()设置的childHandler在客户端连接成功才会执行

 

 

  

 

      

 

 
posted on 2022-04-02 19:39  溪水静幽  阅读(50)  评论(0)    收藏  举报