netty 服务端启动分析

191 阅读12分钟

希望看完这篇文章后,会 哦~~ 原来就个这呀~~~

1. 引导服务配置

下面给出常规的服务端netty 服务创建源码,并由此进行分析;

public class Registry {

    private int port;

    public Registry(int port){
        this.port = port;
    }

    public static void main(String[] args) {
        new Registry(8080).start();
    }

    /**
     *
     */
    private  void start() {

        // Reactor模型,Boss,work
       NioEventLoopGroup bossGroup = new NioEventLoopGroup();
      //  NioEventLoopGroup workGroup = new NioEventLoopGroup();

        // Netty服务,ServerSocketChannel
        ServerBootstrap bootServer = new ServerBootstrap();

        bootServer.group(bossGroup)

                // 主线程所用Channel定义
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))

                // 子线程处理类,Handler
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel client) throws Exception {
                        // 自定义协议解码器
                        client.pipeline()

                                //  add 长度域解码器  ChannelInboundHandler
                                .addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4))

                                // add ChannelOutboundHandler
                                .addLast(new LengthFieldPrepender(4))

                                // add 编码器
                                .addLast(new ObjectEncoder())

                                // add 解码器
                                .addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)))

                                // add 业务处理  ChannelInboundHandler
                                .addLast(new RegisterHandler())
                        ;

                    }
                })
                // .option(ChannelOption.SO_BACKLOG,128)
                .childOption(ChannelOption.SO_KEEPALIVE,true);

        try {
            ChannelFuture future = bootServer.bind(port).sync();
            System.out.println(" LPH RPC Register start listen at " + port);
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
            bossGroup.shutdownGracefully();
            //workGroup.shutdownGracefully();
        }

    }



}

// Reactor模型,Boss,work
NioEventLoopGroup bossGroup = new NioEventLoopGroup();

1.1. NioEventLoopGroup()

NioEventLoopGroup

    /**
     * 🍓
     */
    public NioEventLoopGroup() {
        this(0);
    }

    /**
     *
     */
    public NioEventLoopGroup(int nThreads) {
        this(nThreads, (Executor) null);
    }
    public NioEventLoopGroup(int nThreads, Executor executor) {
        this(nThreads, executor, SelectorProvider.provider());
    }
    public NioEventLoopGroup(
            int nThreads, Executor executor, final SelectorProvider selectorProvider) {
        this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
    }
    public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
                             final SelectStrategyFactory selectStrategyFactory) {
        super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
    }

MultithreadEventExecutorGroup

    /**
     *  创建NIOEventLoop 实例
     */
    protected MultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
        this(nThreads, threadFactory == null ? null : new ThreadPerTaskExecutor(threadFactory), args);
    }

    protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
        this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
    }

    /**
     * Create a new instance.
     *
     * @param nThreads          此实例将使用的线程数。
     * @param executor          要使用的执行器,null 的话使用默认的
     * @param chooserFactory    执行器选择器工厂🏭
     * @param args              透传给 newChild 使用的参数
     */
    protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        // ...

        if (executor == null) {// 定义一个执行器,每次调用execute 时,传入执行体,工厂创建一个线程并执行
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
        
       
        // 定义chilren 事件执行器数组
        children = new EventExecutor[nThreads];

        // chilren 数组内容填充
        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
                children[i] = newChild(executor, args);
                success = true;
            } catch (Exception e) {
                // ...
            } finally {
               // ...
            }
        }

        // 创建选择器工厂
        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);
        }

        // 定义一个仅读的chilren 数组
        Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
        Collections.addAll(childrenSet, children);
        readonlyChildren = Collections.unmodifiableSet(childrenSet);
    }

1.1.2 newChild()

DefaultEventExecutorGroup#newChild

    
    @Override
    protected EventExecutor newChild(Executor executor, Object... args) throws Exception {
        return new DefaultEventExecutor(this, executor, (Integer) args[0], (RejectedExecutionHandler) args[1]);
    }

DefaultEventExecutor#DefaultEventExecutor

    public DefaultEventExecutor(EventExecutorGroup parent, Executor executor, int maxPendingTasks,
                                RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, true, maxPendingTasks, rejectedExecutionHandler);
    }

SingleThreadEventExecutor#SingleThreadEventExecutor

    /**
     * Create a new instance
     *
     * @param parent            EventExecutorGroup是这个实例的父类,并且属于它
     * @param executor          用于执行的执行器
     * @param addTaskWakesUp    当且仅当addTask(Runnable)调用被唤醒时为true
     * @param maxPendingTasks   创建新任务之前的最大挂起任务数
     * @param rejectedHandler   拒绝策略
     */
    protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                        boolean addTaskWakesUp, int maxPendingTasks,
                                        RejectedExecutionHandler rejectedHandler) {
        super(parent);
        this.addTaskWakesUp = addTaskWakesUp;
        this.maxPendingTasks = Math.max(16, maxPendingTasks);
        this.executor = ThreadExecutorMap.apply(executor, this);
        taskQueue = newTaskQueue(this.maxPendingTasks);
        rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
    }

// 这行是生成一个 事件执行器选择器工厂;

// 偶数用:PowerOfTwoEventExecutorChooser (位运算) ,奇数用: GenericEventExecutorChooser (取余)

1.1.3 chooserFactory.newChooser();

public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {

    public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();

    private DefaultEventExecutorChooserFactory() { }

    @Override
    public EventExecutorChooser newChooser(EventExecutor[] executors) {
        if (isPowerOfTwo(executors.length)) {
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {
            return new GenericEventExecutorChooser(executors);
        }
    }
    
     private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

        PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

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

    private static final class GenericEventExecutorChooser implements EventExecutorChooser {
       
        private final AtomicLong idx = new AtomicLong();
        private final EventExecutor[] executors;

        GenericEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[(int) Math.abs(idx.getAndIncrement() % executors.length)];
        }
    }

1.2. channel()

    /**
     * 用来创建Channel实例的类。如果你的Channel实现没有无参数的构造函数,
     * 你可以使用这个或者使用channelFactory(io.nety.channel . channelFactory)。
     */
    public B channel(Class<? extends C> channelClass) {
        return channelFactory(new ReflectiveChannelFactory<C>(
                ObjectUtil.checkNotNull(channelClass, "channelClass")
        ));
    }

    /**
     * @deprecated Use {@link #channelFactory(io.netty.channel.ChannelFactory)} instead.
     */
    @Deprecated
    public B channelFactory(ChannelFactory<? extends C> channelFactory) {
        ObjectUtil.checkNotNull(channelFactory, "channelFactory");
        if (this.channelFactory != null) {
            throw new IllegalStateException("channelFactory set already");
        }

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

ObjectUtil.checkNotNull(channelFactory, "channelFactory");

这行,看着比较迷惑,实际也比较简单,就是检查传入的对象是否为null,null 的话跑出 text NPE;

注: 不要畏惧,干就完了(😁)

    /**
     * 检查给定的参数是否为空。如果是,抛出NullPointerException。否则,返回参数。
     */
    public static <T> T checkNotNull(T arg, String text) {
        if (arg == null) {
            throw new NullPointerException(text);
        }
        return arg;
    }

new ReflectiveChannelFactory(ObjectUtil.checkNotNull(channelClass, "channelClass"))

行看着也比较迷惑,我们看一下具体实现,😄就一简单的反射实现创建对象工厂🏭;

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

    private final Constructor<? extends T> constructor;

    public ReflectiveChannelFactory(Class<? extends T> clazz) {
        ObjectUtil.checkNotNull(clazz, "clazz");
        try {
            this.constructor = clazz.getConstructor();
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) +
                    " does not have a public non-arg constructor", e);
        }
    }

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

    @Override
    public String toString() {
        return StringUtil.simpleClassName(ReflectiveChannelFactory.class) +
                '(' + StringUtil.simpleClassName(constructor.getDeclaringClass()) + ".class)";
    }
}

1.3. childHandler()

设置用于为Channel的请求提供服务的ChannelHandler。

     public ServerBootstrap childHandler(ChannelHandler childHandler) {
        this.childHandler = ObjectUtil.checkNotNull(childHandler, "childHandler");
        return this;
    }

1.4. childOption();

允许指定一个ChannelOption,当Channel实例被创建时(在acceptor接受Channel之后),这个选项会被使用。使用null值删除先前设置的ChannelOption。

    public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value) {
        ObjectUtil.checkNotNull(childOption, "childOption");
        synchronized (childOptions) {
            if (value == null) {
                childOptions.remove(childOption);
            } else {
                childOptions.put(childOption, value);
            }
        }
        return this;
    }

2. 引导服务启动

ChannelFuture future = bootServer.bind(port).sync();

2.1 bind()

    // 根据传入的端口号,生成Socket地址,并绑定
    public ChannelFuture bind(int inetPort) {
        return bind(new InetSocketAddress(inetPort));
    }
    
    // 1) group channelFactory 非null校验, group = new NioEventGroup() 已定义,channelFactory = .channel(NioServerSocketChannel.class)后封装的Factory
    // 2) 调用doBind()
    public ChannelFuture bind(SocketAddress localAddress) {
        validate();
        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();
            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;
        }
    }

2.2 initAndRegister()

AbstractBootstrap

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

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

        return regFuture;
    }

NioServerSocketChannel()

NioServerSocketChannel

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

AbstractNioMessageChannel

public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
   
    protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        super(parent, ch, readInterestOp);
    }

AbstractNioChannel

/**
 * 
 * 通道实现的抽象基类,使用基于选择器的方法。
 */
public abstract class AbstractNioChannel extends AbstractChannel {
   
    /**
     * 创建一个NioChannel 示例
     *
     * @param parent            创建实例的父通道。可能是null
     * @param ch                它操作的基础selectablecchannel
     * @param readInterestOp    设置从selectablecchannel接收数据的操作,这里操作是SelectionKey.OP_ACCEPT
     */
    protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        super(parent);
        this.ch = ch;
        this.readInterestOp = readInterestOp;
        try {
            ch.configureBlocking(false);
        } catch (IOException e) {
            // ...    
        }
    }

AbstractChannel

/**
 * 一个Channel的骨架实现
 */
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
    
    // ...
    
    //	创建一个新示例;
    //  parent : 改通道的父节点,如果没有父节点则为null,  当前分析链路 为null
    protected AbstractChannel(Channel parent) {
        this.parent = parent;
        id = newId();
        unsafe = newUnsafe();
        pipeline = newChannelPipeline();
    }
    
    
    /**
     * 返回一个默认的 Channel 管道
     */
    protected DefaultChannelPipeline newChannelPipeline() {
        return new DefaultChannelPipeline(this);
    }
    
    
    

DefaultChannelPipeline

public class DefaultChannelPipeline implements ChannelPipeline {

    
    protected DefaultChannelPipeline(Channel channel) {
        this.channel = ObjectUtil.checkNotNull(channel, "channel");
        
        // 定义成功之后的 回调Channel
        succeededFuture = new SucceededChannelFuture(channel, null);
        // 
        voidPromise =  new VoidChannelPromise(channel, true);

        tail = new TailContext(this);
        head = new HeadContext(this);

        head.next = tail;
        tail.prev = head;
    }
    final class HeadContext extends AbstractChannelHandlerContext
           implements ChannelOutboundHandler, ChannelInboundHandl 
       private final Unsafe uns 
       HeadContext(DefaultChannelPipeline pipeline) {
           super(pipeline, null, HEAD_NAME, HeadContext.class);
           unsafe = pipeline.channel().unsafe();
           setAddComplete();
       }
            
    // 同时处理字节和消息的特殊的万能处理程序。
    final class TailContext extends AbstractChannelHandlerContext 
            implements ChannelInboundHandler
        TailContext(DefaultChannelPipeline pipeline) {
            super(pipeline, null, TAIL_NAME, TailContext.class);
            setAddComplete();
        }

回归主线

initAndRegister

ServerBootstrap#initAndRegister

    @Override
    void init(Channel channel) {
      
        ChannelPipeline p = channel.pipeline();
       
        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) {
                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));
                    }
                });
            }
        });
    }

// 这里我们进入 addLast方法;

addLast()

DefaultChannelPipeline

    @Override
    public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
        ObjectUtil.checkNotNull(handlers, "handlers");

        for (ChannelHandler h: handlers) {
            if (h == null) {
                break;
            }
            addLast(executor, null, h);
        }

        return this;
    }

    @Override
    public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        synchronized (this) {
            // 校验此handler 是否已添加过
            checkMultiplicity(handler);
                
            // 构建 ChannelHandlerContext  
            newCtx = newContext(group, filterName(name, handler), handler);
            
            // 将我们自定义的 hanlder 插入到(队尾?)  ,
            // 实际上是  header --> 自定义处理handler -->  tail
            addLast0(newCtx);

            
            if (!registered) { 
                // 首次走这里,待补充。。。
                newCtx.setAddPending();
                callHandlerCallbackLater(newCtx, true);
                return this;
            }

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

    private void addLast0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;
    }

register()

这里直接跳转会主线 io.netty.bootstrap.AbstractBootstrap#initAndRegister

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

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

register()

AbstractChannel

        @Override
        public final void register(EventLoop eventLoop, final ChannelPromise promise) {
            ObjectUtil.checkNotNull(eventLoop, "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 { // 注意 我们整体串的是主线程,so 当前线程不在事件循环中,走else 逻辑
                try {
                    eventLoop.execute(new Runnable() {
                        @Override
                        public void run() {
                            register0(promise);
                        }
                    });
                } catch (Throwable t) {
                    // ...
                }
            }
        }

        private void register0(ChannelPromise promise) {
            try {
                // 检查通道是否仍然打开,因为当寄存器调用在eventLoop之外时,它可能会同时关闭
                if (!promise.setUncancellable() || !ensureOpen(promise)) {
                    return;
                }
                boolean firstRegistration = neverRegistered;
                doRegister();
                neverRegistered = false;
                registered = true;

                //	确保我们在实际通知promise之前调用了handlerAdded(…)。这是需要的,因为用户可能已经通过ChannelFutureListener中的管道触发了事件。
                pipeline.invokeHandlerAddedIfNeeded();

                safeSetSuccess(promise);
                
                // 
                pipeline.fireChannelRegistered();
                // 只有在通道从未注册时才触发一个channelActive。这将防止在通道注销和重新注册时触发多个通道活动。
                if (isActive()) {
                    if (firstRegistration) {
                        pipeline.fireChannelActive();
                    } else if (config().isAutoRead()) {
                        // 这个通道在之前注册过,并且设置了autoRead()。这意味着我们需要再次开始读取,以便处理入站数据。
                        // 参见https://github.com/netty/netty/issues/4805
                        beginRead();
                    }
                }
            } catch (Throwable t) {
                // 直接关闭通道,避免FD泄漏。
                closeForcibly();
                closeFuture.setClosed();
                safeSetFailure(promise, t);
            }
        }

doRegister()

AbstractNioChannel

    @Override
    protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {
                // 把Channel 注册到 Selector 上,这里直接关联的是原生 Selector ,和原生 Channel 
                selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
                return;
            } catch (CancelledKeyException e) {
                if (!selected) {
                    // 强制选择器现在选择,因为“取消”的SelectionKey可能仍然被缓存,没有删除,因为还没有调用select .select(..)操作。
                    eventLoop().selectNow();
                    selected = true;
                } else {
                    // 我们之前在选择器上强制了一个选择操作,但是由于某种原因,SelectionKey仍然被缓存。JDK错误?
                    throw e;
                }
            }
        }
    }
    @Override
    public ChannelHandlerContext fireChannelRegistered() {
        invokeChannelRegistered(findContextInbound(MASK_CHANNEL_REGISTERED));
        return this;
    }
    private AbstractChannelHandlerContext findContextOutbound(int mask) {
        AbstractChannelHandlerContext ctx = this;
        EventExecutor currentExecutor = executor();
        do {
            ctx = ctx.prev;
        } while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_OUTBOUND));
        return ctx;
    }

    private static boolean skipContext(
            AbstractChannelHandlerContext ctx, EventExecutor currentExecutor, int mask, int onlyMask) {
        // 确保我们正确地处理MASK_EXCEPTION_CAUGHT,它不包含在MASK_EXCEPTION_CAUGHT中
        return (ctx.executionMask & (onlyMask | mask)) == 0 ||
                // We can only skip if the EventExecutor is the same as otherwise we need to ensure we offload
                // everything to preserve ordering.
                //
                // See https://github.com/netty/netty/issues/10067
                (ctx.executor() == currentExecutor && (ctx.executionMask & mask) == 0);
    }

mask MASK_CHANNEL_REGISTERED : 0000-0000-0000-0010

only Mask MASK_ONLY_INBOUND : 0000-0001-1111-1110

① onlyMask | mask = 0000-0001-1111-1110 即 mask

so ctx.executionMask & (onlyMask | mask)) == 0 等价与②

加入此判断,仅是在异常状态下的兼容处理;分析逻辑时,可以忽略;

② ctx.executionMask & mask ==0, 说明 第二位 为 0 ,即不包含 mask ,跳过

3. 接受用户请求

服务端启动后,最终会注册一个Accept 事件等待客户端的链接;

可以参考2中的分析,核心注册逻辑如下:

    @Override
    void init(Channel channel) {
      
        ChannelPipeline p = channel.pipeline();
       
        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) {
                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));
                    }
                });
            }
        });
    }

NioServerSocketChannel 将自己注册到 Selector 上,通过run() 方法,不断的获取处理相应的 事件;

@Override
protected void run() {
    for (;;) {
        try {
            switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                case SelectStrategy.CONTINUE:
                    continue;
                    
                case SelectStrategy.SELECT:
                    select(wakenUp.getAndSet(false));
                    if (wakenUp.get()) {
                        selector.wakeup();
                    }
                    
                default:
            }

            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 {
                    processSelectedKeys();
                } finally {
                    // Ensure we always run tasks.
                    final long ioTime = System.nanoTime() - ioStartTime;
                    runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
                }
            }
        } catch (Throwable t) {
            handleLoopException(t);
        }
    }
}

EventLoop 是一个死循环,在这个循环中做了3件事情:

1)有条件的等待NIO 事件;

2)处理NIO事件;

3)处理消息队列中的任务;

调用链如下:

private void processSelectedKeys() {
    if (selectedKeys != null) {
        processSelectedKeysOptimized();
    } else {
        processSelectedKeysPlain(selector.selectedKeys());
    }
}

private void processSelectedKeysPlain(Set<SelectionKey> selectedKeys) {
	// ...
    for (;;) {
        final SelectionKey k = i.next();
        final Object a = k.attachment();
        i.remove();
        if (a instanceof AbstractNioChannel) {
            processSelectedKey(k, (AbstractNioChannel) a);
        } else {
            @SuppressWarnings("unchecked")
            NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
            processSelectedKey(k, task);
        }
        // ...
    }
}

private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
    // ...
    try {
        // ...
        if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
            unsafe.read();
        }
    } catch (CancelledKeyException ignored) {
        unsafe.close(unsafe.voidPromise());
    }
}

这里的 unsafe 是 bossGroup 线程中 NioServerSocketChannel 的AbstractNioMessageChannel$NioMessageUnsafe 类型的对象。我们进入到其read()方法中:

@Override
public void read() {
    assert eventLoop().inEventLoop();
    final ChannelConfig config = config();
    final ChannelPipeline pipeline = pipeline();
    final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
    allocHandle.reset(config);

    boolean closed = false;
    Throwable exception = null;
    try {
        try {
            do {
                int localRead = doReadMessages(readBuf);
                if (localRead == 0) {
                    break;
                }
                if (localRead < 0) {
                    closed = true;
                    break;
                }

                allocHandle.incMessagesRead(localRead);
            } while (allocHandle.continueReading());
        } catch (Throwable t) {
            exception = t;
        }

        int size = readBuf.size();
        for (int i = 0; i < size; i ++) {
            readPending = false;
            pipeline.fireChannelRead(readBuf.get(i));
        }
        readBuf.clear();
        allocHandle.readComplete();
        pipeline.fireChannelReadComplete();
        
        // ... 
       
    } 
}

doReadMessages(readBuf) 方法,其中的变量 readBuf 是一个List,也就是一个容器,该方法的作用是读取 bossGroup 线程中的 NioServerSocketChannel 接收到的请求,并把这些请求放进容器:

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

说明:该方法是通过 ServerSocket 的accept()方法获取到一个TCP连接,然后将其封装为Netty的NioSocketChannel对象,最后添加到容器中;

public static SocketChannel accept(final ServerSocketChannel serverSocketChannel) throws IOException {
    try {
        return AccessController.doPrivileged(new PrivilegedExceptionAction<SocketChannel>() {
            @Override
            public SocketChannel run() throws IOException {
                return serverSocketChannel.accept();
            }
        });
    } catch (PrivilegedActionException e) {
        throw (IOException) e.getCause();
    }
}

循环 readBuf 这个容器中的所有请求,执行 pipeline.fireChannelRead(readBuf.get(i))

b.group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .option(ChannelOption.SO_BACKLOG, 100)
        .handler(new LoggingHandler(LogLevel.INFO))// 将会在每次客户端连接时调用
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline p = ch.pipeline();
                if (sslCtx != null) {
                    p.addLast(sslCtx.newHandler(ch.alloc()));
                }
                //p.addLast(new LoggingHandler(LogLevel.INFO));// 将会在每次客户端有事件发生时调用
                p.addLast(new EchoServerHandler());
            }
        });

handler() : 在每次有客户端连接时会调用

childHandler() :在客户端连接建立成功之后有读写等操作时触发。

服务端的代码中,我们仅显示的注册了LoggingHandler, 但netty 会自动的帮我们 注入 Head、LoggingHandler、ServerBootstrapAcceptor、Tail。

这里我们着重看 ServerBootstrapAcceptor,因为它 起到中转的作用,接受用户端的请求,并将链接

转到workGroup, 同时为 每个SocketChannel 注册我们在childHandler() 方法中指定的handler ;

public void channelRead(ChannelHandlerContext ctx, Object msg) {
    
     // ① 将msg 强转为 Channel ,实际上是 NioSocketChannel
     final Channel child = (Channel) msg;
        
     // ② 为child 的pepeline 添加自定义的 handler 
     child.pipeline().addLast(childHandler);

     // ③ 设置NioSocketChannel 的各种属性
     setChannelOptions(child, childOptions, logger);

     for (Entry<AttributeKey<?>, Object> e: childAttrs) {
         child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
     }

     try {
     	 // ④ 将客户端连接注册到workerGroup的线程池中
         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);
     }
 }

至此,针对客户端的连接就完成了,接下来可以监听事件了;

整体流程如下:

  • 1)服务端启动时 创建的NioEventLoop 对象 会通过死循环的方式轮询监听有没有新的连接过来;
  • 2)监听到有新的连接过来(即 Accept 事件)时,就会创建一个NioSocketChannel ,并将其置于一个容器中;
  • 3)遍历上述容器,执行 fireChannelRead() 方法,使每一个新进来的客户端连接都经过我们在handler() 方法中指定的handler的处理(即执行这些handler 的channelRead() 方法),需要特别注意的是,netty 会隐式的为我们注册Head、ServerBootstrapAcceptor、Tail 这三个handler, 因此也会执行这三个handler 的channelRead() 方法;
  • 4)在执行ServerBootstrapAcceptor 的channelRead() 方法时,会将2)中创建的NioSocketChannel转交给workerGroup( 将其注册到workGroup 中的EventLoop 中,监听读写等事件),同时为这些NioSocketChannel 绑定我们在 childHandler() 中指定的handler;

4. 整体流程图

参见

csdn-Netty20——Netty 核心组件 EventLoop 剖析

netty-接受用户请求过程分析