(二)Netty服务启动过程源码分析 — 初始化Channel

前言

上一篇分析了服务端启动类的源码,接下来我们在上一篇的代码的基础上,一步一步的看一下启动过程中是如何运作的。

由于启动过程代码调用链较长,所以分为两部分来分析。

本文分析的是启动过程中的初始化部分。


正文

io.netty.example.echo.EchoServer

// 启动类中这一句是开始启动,我们跟进到bind方法中
ChannelFuture f = b.bind(PORT).sync();
io.netty.bootstrap.AbstractBootstrap

    public ChannelFuture bind(SocketAddress localAddress) {
        // 验证ServerBootstrap传进来的参数
        validate();
        // 继续跟进去
        return doBind(ObjectUtil.checkNotNull(localAddress, "localAddress"));
    }

    private ChannelFuture doBind(final SocketAddress localAddress) {
        // 初始化和注册动作,返回Future(异步操作),见另外一个代码块
        final ChannelFuture regFuture = initAndRegister();

        final Channel channel = regFuture.channel();
        // 如果注册过程中抛错了,直接返回
        if (regFuture.cause() != null) {
            return regFuture;
        }


        // 判断注册future有没有完成(可以看到,除非是失败,最后都会调用doBind0())
        if (regFuture.isDone()) {
            // 成功结束了的话,执行dobind0方法
            ChannelPromise promise = channel.newPromise(); // Promise,一种可以写的Future
            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();
                        doBind0(regFuture, channel, localAddress, promise);
                    }
                }
            });
            return promise;
        }
    }
io.netty.bootstrap.AbstractBootstrap

    // 初始化并且注册过程
    final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            // 这个channelFactory是ReflectiveChannelFactory,在创建ServerBootStrap的时候注册的.channel(NioServerSocketChannel.class),可以在启动类中跟进去看源码
            // 所以这个channel是NioServerSocketChannel
            channel = channelFactory.newChannel();
            // 【重要代码】为NioServerSocketChannel添加handler
            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);
        }

        // 【重要代码】异步注册到NioEventLoop(selector)中,这部分我们在下一篇中详细分析
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }

        return regFuture;
    }


// 具体初始化过程
io.netty.bootstrap.ServerBootstrap

    @Override
    void init(Channel channel) {
        // 根据初始化的option,设置channel的参数
        setChannelOptions(channel, newOptionsArray(), logger);
        // 根据初始化的attr,设置channel的属性
        setAttributes(channel, attrs0().entrySet().toArray(EMPTY_ATTRIBUTE_ARRAY));

        ChannelPipeline p = channel.pipeline();

        // 下面四个都是workerGroup的属性
        final EventLoopGroup currentChildGroup = childGroup;
        final ChannelHandler currentChildHandler = childHandler;
        final Entry<ChannelOption<?>, Object>[] currentChildOptions;
        synchronized (childOptions) {
            currentChildOptions = childOptions.entrySet().toArray(EMPTY_OPTION_ARRAY);
        }
        final Entry<AttributeKey<?>, Object>[] currentChildAttrs = childAttrs.entrySet().toArray(EMPTY_ATTRIBUTE_ARRAY);

        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) {
                final ChannelPipeline pipeline = ch.pipeline();
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    // 这里添加的是注册时候的handler :LoggingHandler
                    pipeline.addLast(handler);
                }

                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        // pipeline异步添加一个负责接收客户端事件的handler:ServerBootstrapAcceptor,并且把workerGroup的属性当做参数传进去,
                        //所以这个ServerBootstrapAcceptor是netty默认会加到pipeline中,不用我们手动添加
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });
            }
        });
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值