Netty源码解析(六) —— 服务端channel如何完成注册

先看ServerBootstrap的继承关系
这里写图片描述


ServerBootstrap的成员变量

    //worker group
    private volatile EventLoopGroup childGroup;
    //设置进来的childHandler
    private volatile ChannelHandler childHandler;

AbstractBootstrap:

    /**
     * EventLoopGroup 对象  boss group
     */
    volatile EventLoopGroup group;
    /**
     * channel工厂用于创建channel
     */
    @SuppressWarnings("deprecation")
    private volatile ChannelFactory<? extends C> channelFactory;
    /**
     * 本地地址
     */
    private volatile SocketAddress localAddress;
    /**
     * 可选项集合
     */
    private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
    /**
     * 属性集合
     */
    private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();
    /**
     * 启动的时候设置的处理器  .handler(new LoggingHandler(LogLevel.INFO))
     * 设置进来的
     */
    private volatile ChannelHandler handler;

先看服务端启动的代码

        //创建boss worker线程
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        final EchoServerHandler serverHandler = new EchoServerHandler();
        try {
            //创建netty服务端启动器
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)//给启动器配置boss worker
             .channel(NioServerSocketChannel.class)//设置使用NioServerSocketChannel
             .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(serverHandler);
                 }
             });

io.netty.bootstrap.ServerBootstrap#group(io.netty.channel.EventLoopGroup,io.netty.channel.EventLoopGroup)

    public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
        super.group(parentGroup);
        if (childGroup == null) {
            throw new NullPointerException("childGroup");
        }
        if (this.childGroup != null) {
            throw new IllegalStateException("childGroup set already");
        }
        //保存到worker group
        this.childGroup = childGroup;
        return this;
    }
    public B group(EventLoopGroup group) {
        if (group == null) {
            throw new NullPointerException("group");
        }
        if (this.group != null) {//不允许重复设置
            throw new IllegalStateException("group set already");
        }
        //保存到boss group
        this.group = group;
        return self();
    }

io.netty.bootstrap.AbstractBootstrap#channel

    /**
     * 设置要被实例化的 Channel 的类
     */
    public B channel(Class<? extends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
    }

ReflectiveChannelFactory工厂,用于反射生产channel对象

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

    //Channel 对应的类
    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 {
            // 反射调用默认构造方法,创建 Channel 对象
            return clazz.getConstructor().newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + clazz, t);
        }
    }

这个工厂模式一目了然
io.netty.bootstrap.AbstractBootstrap#handler(io.netty.channel.ChannelHandler)

    /**
     * the {@link ChannelHandler} to use for serving the requests.
     * 设置创建 Channel 的处理器
     */
    public B handler(ChannelHandler handler) {
        if (handler == null) {
            throw new NullPointerException("handler");
        }
        //保存处理器
        this.handler = handler;
        return self();
    }
    public ServerBootstrap childHandler(ChannelHandler childHandler) {
        if (childHandler == null) {
            throw new NullPointerException("childHandler");
        }
        //保存到childHandler处理器
        this.childHandler = childHandler;
        return this;
    }

io.netty.bootstrap.AbstractBootstrap#bind(int)根据调用链,最后走到
.bootstrap.AbstractBootstrap#doBind

    private ChannelFuture doBind(final SocketAddress localAddress) {
        // 初始化并注册一个 Channel 对象,因为注册是异步的过程,所以返回一个 ChannelFuture 对象。
        final ChannelFuture regFuture = initAndRegister();
        final Channel channel = regFuture.channel();
        if (regFuture.cause() != null) {// 若发生异常,直接进行返回
            return regFuture;
        }

        // 绑定 Channel 的端口,并注册 Channel 到 SelectionKey 中。
        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;
        }
    }

io.netty.bootstrap.AbstractBootstrap#initAndRegister

    final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            // 创建 Channel 对象(工厂模式反射创建)
            channel = channelFactory.newChannel();
            // 初始化 Channel 配置
            init(channel);
        } catch (Throwable t) {
            if (channel != null) {// 已创建 Channel 对象
                channel.unsafe().closeForcibly();// 强制关闭 Channel
                /**
                 * 因为创建 Channel 对象失败,所以需要创建一个 FailedChannel 对象,设置到 DefaultChannelPromise 中才可以返回。
                 */
                return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
            }
            return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
        }

        /**
         * 首先获得 EventLoopGroup 对象,后调用 EventLoopGroup#register(Channel) 方法,注册 Channel 到 EventLoopGroup 中。
         * 实际在方法内部,EventLoopGroup 会分配一个 EventLoop 对象,将 Channel 注册到其上。
         *
         * 注册 Channel 到 EventLoopGroup 中
         * config().group()拿到的是boss线程调度
         *
         */
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                // 强制关闭 Channel
                channel.unsafe().closeForcibly();
            }
        }
        return regFuture;
    }

io.netty.bootstrap.AbstractBootstrap#init初始化 Channel 配置

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

        //设置options  attrs给服务端的channel对象
        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初始化的时候会创建一个pipLine
        ChannelPipeline p = channel.pipeline();

        //这个就是work 的线程 维护的线程个数是cpu*2
        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));
        }

        //给pipLine添加handler  ChannelInitializer
        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) throws Exception {
                final ChannelPipeline pipeline = ch.pipeline();
                //拿到配置中的handler
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    //添加到pipline中去  head-->handler-->tail
                    pipeline.addLast(handler);
                }

                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        //pipline会默认添加一个acceptor,是设置给ServerBootStrap的
                        //ServerBootstrapAcceptor  专门处理新连接accept进来的处理
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });
            }
        });
    }

ServerBootstrapAcceptor给pipLine添加一个新连接到来的处理器,以便于服务端channel在处理accept事件的时候给客户端channel注册事件
ChannelFuture regFuture = config().group().register(channel);这个方法调用boss group来注册服务端的channel到NioEventLoop中去
io.netty.channel.MultithreadEventLoopGroup#register(io.netty.channel.Channel)

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

同上篇,next回去调用线程选择器,选择一个NioEventLoop来完成注册
io.netty.channel.SingleThreadEventLoop#register(io.netty.channel.Channel)

    /**
     * 注册channel
     * @param channel
     * @return
     */
    @Override
    public ChannelFuture register(Channel channel) {
        return register(new DefaultChannelPromise(channel, this));
    }

    @Override
    public ChannelFuture register(final ChannelPromise promise) {
        ObjectUtil.checkNotNull(promise, "promise");
        //转交给unsafe来进行注册
        promise.channel().unsafe().register(this, promise);
        return promise;
    }

io.netty.channel.AbstractChannel.AbstractUnsafe#register

       /**
         * 注册channel到selector
         * @param eventLoop
         * @param promise
         */
        @Override
        public final void register(EventLoop eventLoop, final ChannelPromise promise) {
            ....
            //保存事件处理线程
            AbstractChannel.this.eventLoop = eventLoop;
            /**
             * 在工作线程知己进行注册
             */
            if (eventLoop.inEventLoop()) {
                //注册channel
                register0(promise);
            } else {
                try {
                    //否则执行task任务  添加到队列  异步进行调度
                    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);
                }
            }
        }

eventLoop.execute(new Runnable() )此时boss线程还未启动,所以会调用eventLoop的execute方法
io.netty.util.concurrent.SingleThreadEventExecutor#execute

    @Override
    public void execute(Runnable task) {
        if (task == null) {
            throw new NullPointerException("task");
        }
        //判断正在执行任务的线程是否是eventloop已经保存的线程
        boolean inEventLoop = inEventLoop();
        addTask(task);
        //如果不是在eventloop线程证明还没启动轮询和任务调度run方法
        //则启动线程
        if (!inEventLoop) {
            //启动线程
            startThread();
            if (isShutdown() && removeTask(task)) {
                reject();
            }
        }

        if (!addTaskWakesUp && wakesUpForTask(task)) {
            wakeup(inEventLoop);
        }
    }

io.netty.util.concurrent.SingleThreadEventExecutor#startThread

    private void startThread() {
        //状态值是未启动过
        if (state == ST_NOT_STARTED) {
            if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
                try {
                    //真正启动的逻辑
                    doStartThread();
                } catch (Throwable cause) {
                    STATE_UPDATER.set(this, ST_NOT_STARTED);
                    PlatformDependent.throwException(cause);
                }
            }
        }
    }

如果没启动过,那么doStartThread开始启动

    private void doStartThread() {
        assert thread == null;
        //交给线程执行器去执行代码 ThreadPerTaskExecutor
        executor.execute(new Runnable() {
            @Override
            public void run() {
                //保存当前线程异步任务的线程
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }
                boolean success = false;
                updateLastExecutionTime();
                try {
                    //启动NioEventLoop的run()方法  进行selector轮询
                    SingleThreadEventExecutor.this.run();
                    success = true;
                } catch (Throwable t) {

使用线程执行器开启线程来执行NioEventLoop中的run方法,从而开始不断的select—>processKey—>runAllTask()
回头看io.netty.channel.AbstractChannel.AbstractUnsafe#register0

        private void register0(ChannelPromise promise) {
            try {
                if (!promise.setUncancellable() || !ensureOpen(promise)) {
                    return;
                }
                boolean firstRegistration = neverRegistered;
                //执行注册channel的逻辑
                doRegister();
                neverRegistered = false;
                registered = true;

                //通知pipline添加操作
                pipeline.invokeHandlerAddedIfNeeded();

                safeSetSuccess(promise);
                //通知pipline registe事件
                pipeline.fireChannelRegistered();

                if (isActive()) {
                    if (firstRegistration) {
                        //通知pipline的active事件  header->tail  active
                        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);
            }
        }

selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);

doRegister调用java原生的channel注册到NioEventLoop中的selector中去,不关心任何事件0,并且把channel设置给attachment,此时isActive()返回false,
初始化和注册都走完了,现在回头看io.netty.bootstrap.AbstractBootstrap#doBind0

    private static void doBind0(
            final ChannelFuture regFuture, final Channel channel,
            final SocketAddress localAddress, final ChannelPromise promise) {
        /**
         * 把注册任务交给eventLoop   添加到task队列
         * 在run方法里面会有处理任务的逻辑代码
         */
        channel.eventLoop().execute(new Runnable() {
            @Override
            public void run() {
                // 注册成功,绑定端口
                if (regFuture.isSuccess()) {
                    channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
                } else {// 注册失败,回调通知 promise 异常
                    promise.setFailure(regFuture.cause());
                }
            }
        });
    }

io.netty.channel.AbstractChannel#bind(java.net.SocketAddress,io.netty.channel.ChannelPromise)

    @Override
    public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
        //调用pipline的bind方法
        return pipeline.bind(localAddress, promise);
    }

io.netty.channel.DefaultChannelPipeline#bind(java.net.SocketAddress,io.netty.channel.ChannelPromise)

    @Override
    public final ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
        //调用tail的bind方法  TailContext类
        return tail.bind(localAddress, promise);
    }

io.netty.channel.AbstractChannelHandlerContext#bind(java.net.SocketAddress, io.netty.channel.ChannelPromise)从tail尾部开始找

    @Override
    public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) {
        .....

        //向前找找到  HeadContext
        final AbstractChannelHandlerContext next = findContextOutbound();
        EventExecutor executor = next.executor();
        //判断是否是在eventLoop线程
        if (executor.inEventLoop()) {
            //执行HeadContext  invokeBind
            next.invokeBind(localAddress, promise);
        } else {
            safeExecute(executor, new Runnable() {
                @Override
                public void run() {
                    next.invokeBind(localAddress, promise);
                }
            }, promise, null);
        }
        return promise;
    }
    /**
     * 一直往前找  找到inBound
     * @return
     */
    private AbstractChannelHandlerContext findContextOutbound() {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.prev;
        } while (!ctx.outbound);
        return ctx;
    }

这个方法是在pipLine链表中的tail尾部向前找节点,最终找到headContext节点
io.netty.channel.DefaultChannelPipeline.HeadContext#bind

        @Override
        public void bind(
                ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise)
                throws Exception {
            //调用unsafe的bind方法
            unsafe.bind(localAddress, promise);
        }

io.netty.channel.AbstractChannel.AbstractUnsafe#bind

        @Override
        public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {

            .....

            boolean wasActive = isActive();
            try {
                //绑定端口操作
                doBind(localAddress);
            } catch (Throwable t) {
                safeSetFailure(promise, t);
                closeIfClosed();
                return;
            }

            if (!wasActive && isActive()) {
                //传播通知事件active
                invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        pipeline.fireChannelActive();
                    }
                });
            }

            safeSetSuccess(promise);
        }

doBind方法调用原生channel对象完成绑定,isActive()返回true,进行事件传播最终调用到io.netty.channel.DefaultChannelPipeline.HeadContext#channelActive

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            ctx.fireChannelActive();

            //注册read关心事件
            readIfIsAutoRead();
        }
        private void readIfIsAutoRead() {
            if (channel.config().isAutoRead()) {
                channel.read();
            }
        }

在次调用到channel的read方法,调用pipline的read方法

    @Override
    public Channel read() {
        pipeline.read();
        return this;
    }

最后调用到io.netty.channel.DefaultChannelPipeline.HeadContext#read

        private final Unsafe unsafe;

        HeadContext(DefaultChannelPipeline pipeline) {
            super(pipeline, null, HEAD_NAME, false, true);
            //从channel中取出unsafe
            unsafe = pipeline.channel().unsafe();
            setAddComplete();
        }
        @Override
        public void read(ChannelHandlerContext ctx) {
            unsafe.beginRead();
        }

io.netty.channel.AbstractChannel.AbstractUnsafe#beginRead

        @Override
        public final void beginRead() {
            assertEventLoop();

            if (!isActive()) {
                return;
            }

            try {
                doBeginRead();
            } catch (final Exception e) {
                invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        pipeline.fireExceptionCaught(e);
                    }
                });
                close(voidPromise());
            }
        }

然后开始注册感兴趣的事件

    @Override
    protected void doBeginRead() throws Exception {
        // Channel.read() or ChannelHandlerContext.read() was called
        final SelectionKey selectionKey = this.selectionKey;
        if (!selectionKey.isValid()) {
            return;
        }

        readPending = true;

        //取出来构造参数传进来的ops
        final int interestOps = selectionKey.interestOps();
        if ((interestOps & readInterestOp) == 0) {
            //注册感兴趣事件
            selectionKey.interestOps(interestOps | readInterestOp);
        }
    }

这段代码的逻辑和上一篇客户端的注册感兴趣事件基本一样,

    /**
     * Create a new instance using the given {@link ServerSocketChannel}.
     */
    public NioServerSocketChannel(ServerSocketChannel channel) {
        super(null, channel, SelectionKey.OP_ACCEPT);
        config = new NioServerSocketChannelConfig(this, javaChannel().socket());
    }

到此就明了了,服务端的channel默认是对accept事件感兴趣

猜你喜欢

转载自blog.csdn.net/u011702633/article/details/81984687