Netty服务端源码阅读笔记(四)ServerBootstrap(1)

16 篇文章 0 订阅

ServerBootstrap用于关联服务端的各组件

回顾服务端代码和netty的reactor模型,可以看到出,parentGroup用来处理连接请求,childGroup用于处理接下来的操作

new 方法并没有什么操作,服务端关联组件ServerBootstrap, 继承于AbstractBootstrap,父子类的group、options、attr、handler变量,对应parentGroup和childGroup

public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
    private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
    private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>();

    // 这个config就是用来获取当前对象的各种配置,childGroup、childHandler、attr等等
    private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);
    private volatile EventLoopGroup childGroup;
    private volatile ChannelHandler childHandler;

    public ServerBootstrap() {
    }
}

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
  volatile EventLoopGroup group;
    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>();
    private volatile ChannelHandler handler;

    AbstractBootstrap() {
    }
}
bootstrap.group(parentGroup, childGroup)
.option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.SO_KEEPALIVE, true)

这三步不看代码了,字面意思,就是赋值到对应的变量上 

.channel(NioServerSocketChannel.class)

 // 初始化channel工厂,内部newChannel()方法,调用会new一个新的NioServerSocketChannel
 io.netty.bootstrap.AbstractBootstrap.channel(Class<? extends C>)

   public B channel(Class<? extends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        // 返回一个channelFactory
        return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
    }

    public B channelFactory(ChannelFactory<? extends C> channelFactory) {
        if (channelFactory == null) {
            throw new NullPointerException("channelFactory");
        }
        if (this.channelFactory != null) {
            throw new IllegalStateException("channelFactory set already");
        }
        this.channelFactory = channelFactory;
        return this;
    }

    //io.netty.channel.ReflectiveChannelFactory#newChannel
    public T newChannel() {
        try {
            // 使用反射机制,调用其无参构造器,创建channel
            return constructor.newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
        }
    }

new NioServerSocketChannel();
 NioServerSocketChannel就是原生ServerSocketChannel的封装

    public NioServerSocketChannel() {
        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
    }
    
    private static java.nio.channels.ServerSocketChannel newSocket(SelectorProvider provider) {
        try {
            // 这就是原生NIO代码中获取Server端Channel的代码ServerSocketChannel.open()底层
            return provider.openServerSocketChannel();
        } catch (IOException e) {
            throw new ChannelException("Failed to open a server socket.", e);
        }
    }

    public NioServerSocketChannel(java.nio.channels.ServerSocketChannel channel) {
        // 有设置channel非阻塞,初始化pipeline(DefaultChannelPipeline),unsafe类等操作
        super(null, channel, 16);
        config = new NioServerSocketChannelConfig(this, javaChannel().socket(), null);
    }

   protected AbstractChannel(Channel parent) {
        this.parent = parent;
        // 为Netty的channel生成id
        id = newId();
        // 底层操作对象   AbstractNioMessageChannel.NioMessageUnsafe对象
        unsafe = newUnsafe();
        // 创建当前channel所绑定的channelPipeline ,DefaultChannelPipeline对象
        pipeline = newChannelPipeline();
    }

 .childHandler,字面意思,为childHandler赋值,先不解释ChannelInitializer,内部pipeliine.addLast并没执行,下边执行的时候再跟

.childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new ObjectEncoder());
                            pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE,
                                    ClassResolvers.cacheDisabled(null)));
                            pipeline.addLast(new RpcServerHandler(registerMap));
                        }
                    });

 ChannelFuture future = bootstrap.bind(8888).sync();

原生NIO编程中,初始化的时候有两步,绑定端口号和注册channel连接事件到selector

   socketChannel.bind(new InetSocketAddress(8080));
   socketChannel.register(selector,SelectionKey.OP_ACCEPT);

bind(8888)中就是做这两步,对应就是initAndRegister()方法和doBind0()方法,主要关注这两

// 直接看核心代码
// 注册和绑定端口是另开一个线程去操作,所以会返回一个异步结果对象ChannelFuture()来关联异步结果
// 外界判断异步操作是否完成,isDone()
// bind(8888).sync()的sync方法也是阻塞线程,直到这个Promise对象已经被标识完成
 private ChannelFuture doBind(final SocketAddress localAddress) {
        // 创建、初始化channel,并将其注册到Selector
        final ChannelFuture regFuture = initAndRegister();
        // 从异步结果中获取channel
        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.
            // 创建一个可修改的异步结果对象channelFuture
            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;
        }
    }

initAndRegister()

创建了ServerSocketChannel,并初始化,然后注册到parentGroup中(挑选一个NioEventLoop注册,一个Channel绑定一个NioEventLoop,一个NioEventLoop可以被多个Channel绑定)

关注点放在 init(channel)初始化channel 和 NioeventLoop.register(channel)注册NioServerSocketChannel

   final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            // 创建一个channel  new NioServerSocketChannel
            channel = channelFactory.newChannel();
            // 初始化NioServerSocketChannel
            init(channel);
        } catch (Throwable t) {
           // 忽略了部分代码,报异常后直接返回失败的Promise
        }

        // config().group()获取了ServerBootStrap父类中的group,即我们代码的parentGroup
        // 将当前channel注册给selector
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }

        return regFuture;
    }

// NioEventLoopGroup继承MultithreadEventLoopGroup
// io.netty.channel.MultithreadEventLoopGroup#register(io.netty.channel.Channel)
    public ChannelFuture register(Channel channel) {
        // 从parentGroup中根据算法选择一个NioeventLoop来完成注册
        return next().register(channel);
    }

 doBind0

获取channel绑定的那个NioEventLoop, 用内部绑定的线程来绑定

    private static void doBind0(
            final ChannelFuture regFuture, final Channel channel,
            final SocketAddress localAddress, final ChannelPromise promise) {

        // This method is invoked before channelRegistered() is triggered.  Give user handlers a chance to set up
        // the pipeline in its channelRegistered() implementation.
        channel.eventLoop().execute(new Runnable() {
            @Override
            public void run() {
                if (regFuture.isSuccess()) {
                    channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
                } else {
                    promise.setFailure(regFuture.cause());
                }
            }
        });
    }

全放在一块太乱了,我分开写了

总结之,serverBootStrap.bind(),分为两步

一、创建channel并注册channel到selector,其中又分为

          1)初始化channel  --  Netty服务端源码阅读笔记(四)ServerBootstrap(2)

          2)NioEventLoop注册channel  --  Netty服务端源码阅读笔记(四)ServerBootstrap(3)

二、为channel绑定端口号  --  Netty服务端源码阅读笔记(四)ServerBootstrap(4)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值