Netty源码(三)ServerBootstrap

ServerBootstrap

ServerBootstrap的作用是用来启动Netty服务端

类继承结构

在这里插入图片描述

AbstractBootstrap

重要属性

// 主EventLoopGroup,当协议是面向连接时,主要用来接收连接
volatile EventLoopGroup group;
@SuppressWarnings("deprecation")
// 用来生成channel
private volatile ChannelFactory<? extends C> channelFactory;
// 绑定的本地地址
private volatile SocketAddress localAddress;
// 用来配置channel
private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
// 配置channel的attachment
private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();
// handler
private volatile ChannelHandler handler;

self

可以看到就是返回当前对象

private B self() {
   return (B) this;
}

group

简单地将入参设置到group属性上

public B group(EventLoopGroup group) {
     if (group == null) {
         throw new NullPointerException("group");
     }
     if (this.group != null) {
         throw new IllegalStateException("group set already");
     }
     this.group = group;
     return self();
 }

attr

使用入参来设置attrs属性,当value为null时,会将对应的key删除掉

public <T> B attr(AttributeKey<T> key, T value) {
   if (key == null) {
        throw new NullPointerException("key");
    }
    if (value == null) {
        synchronized (attrs) {
            attrs.remove(key);
        }
    } else {
        synchronized (attrs) {
            attrs.put(key, value);
        }
    }
    return self();
}

channel

public B channel(Class<? extends C> channelClass) {
    if (channelClass == null) {
        throw new NullPointerException("channelClass");
    }
    // 创建一个ReflectiveChannelFactory,然后设置到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 self();
}

ReflectiveChannelFactory从名字也可以看出,是一个通过反射的方式来产生channel的工厂

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 {
        	// 通过反射来创建一个channel
            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";
    }
}

handler

简单地赋值

public B handler(ChannelHandler handler) {
    if (handler == null) {
        throw new NullPointerException("handler");
    }
    this.handler = handler;
    return self();
}

option

将指定的option添加到options这个map中

public <T> B option(ChannelOption<T> option, T value) {
    if (option == null) {
        throw new NullPointerException("option");
    }
    if (value == null) {
        synchronized (options) {
            options.remove(option);
        }
    } else {
        synchronized (options) {
            options.put(option, value);
        }
    }
    return self();
}

bind

下面看下如何创建channel并绑定到本地端口

public ChannelFuture bind() {
    validate();
    SocketAddress localAddress = this.localAddress;
    if (localAddress == null) {
        throw new IllegalStateException("localAddress not set");
    }
    return doBind(localAddress);
}
private ChannelFuture doBind(final SocketAddress localAddress) {
    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.
        ChannelPromise promise = channel.newPromise();
        // 将当前channel绑定到本地端口作为一个任务,提交到channel绑定的eventloop进行执行
        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);
        // 设置监听器,监听完成事件,当事件完成后,设置promise,如果注册成功,进行绑定操作
        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

主要做的就是创建一个channel,然后调用子类的实现对该channel进行初始化,最后将创建的channel注册到eventloop上

final ChannelFuture initAndRegister() {
    Channel channel = null;
    try {
    	// 使用channelFactory生成一个channel
        channel = channelFactory.newChannel();
        // 子类来实现channel的初始化
        init(channel);
    } catch (Throwable t) {
        if (channel != null) {
            // channel can be null if newChannel crashed (eg SocketException("too many open files"))
            channel.unsafe().closeForcibly();
            // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
            return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
        }
        // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
        return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
    }

	// 获取Bootstrap配置,通过配置来获取group,将channel注册到group上
	// regFuture是注册的结果
    ChannelFuture regFuture = config().group().register(channel);
    if (regFuture.cause() != null) {
        if (channel.isRegistered()) {
            channel.close();
        } else {
            channel.unsafe().closeForcibly();
        }
    }

    // If we are here and the promise is not failed, it's one of the following cases:
    // 1) If we attempted registration from the event loop, the registration has been completed at this point.
    //    i.e. It's safe to attempt bind() or connect() now because the channel has been registered.
    // 2) If we attempted registration from the other thread, the registration request has been successfully
    //    added to the event loop's task queue for later execution.
    //    i.e. It's safe to attempt bind() or connect() now:
    //         because bind() or connect() will be executed *after* the scheduled registration task is executed
    //         because register(), bind(), and connect() are all bound to the same thread.

    return regFuture;
}
doBind0
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提交任务
    // 如果channel成功注册到eventLoopGroup,那么开始执行绑定
    // 如果注册失败,将失败原因写入到promise中
    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());
            }
        }
    });
}
具体注册操作

下面看下将Channel注册eventLoopGroup上的具体过程,因为最常用的是NIoEvenLoopGroup,所以下面将以NioServerSocketChannel的注册为例

NioServerSocketChannel的创建

下面是NiosServerSocketChannel的类继承结构
在这里插入图片描述
首先看下NioServerSocketChannel的创建

// selector提供者
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
// socketChannel的配置
private final ServerSocketChannelConfig config;
public NioServerSocketChannel() {
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
private static ServerSocketChannel newSocket(SelectorProvider provider) {
    try {
        /**
         *  Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
         *  {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise.
         *
         *  See <a href="https://github.com/netty/netty/issues/2308">#2308</a>.
         */
        return provider.openServerSocketChannel();
    } catch (IOException e) {
        throw new ChannelException(
                "Failed to open a server socket.", e);
    }
}
public ServerSocketChannel openServerSocketChannel() throws IOException {
   // java 原生的nio socket channel
   return new ServerSocketChannelImpl(this);
}
public NioServerSocketChannel(ServerSocketChannel channel) {
   // 调用父类构造方法
   super(null, channel, SelectionKey.OP_ACCEPT);
   config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
// AbstractNioMessageChannel
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
 // 继续调用父类构造方法
 super(parent, ch, readInterestOp);
}
// AbstractNioChannel
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
    super(parent);
    this.ch = ch;
    // 设置感兴趣的事件,当前例子是OP_ACCEPT
    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);
    }
}
protected AbstractChannel(Channel parent) {
    this.parent = parent;
    // 设置当前channel的id
    id = newId();
    // 设置unsafe
    unsafe = newUnsafe();
    // 设置pipeline
    pipeline = newChannelPipeline();
}
NioEventLoopGroup的注册
// MultithreadEventLoopGroup
public ChannelFuture register(Channel channel) {
 return next().register(channel);
}
// SingleThreadEventLoop
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;
}
// AbstractUnsafe
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
    if (eventLoop == null) {
        throw new NullPointerException("eventLoop");
    }
    // <1>判断是否注册过
    if (isRegistered()) {
        promise.setFailure(new IllegalStateException("registered to an event loop already"));
        return;
    }
    // <2>判断channel的类型和eventloop的类型是否匹配
    // 如果channel的类型是AbstractNioChannel,那么这里会要求eventLoop是NioEventLoop
    if (!isCompatible(eventLoop)) {
        promise.setFailure(
                new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
        return;
    }

	// <3>赋值eventloop
    AbstractChannel.this.eventLoop = eventLoop;

	// 判断当前线程是否是eventLoop绑定的线程
    if (eventLoop.inEventLoop()) {
    	// 真实执行注册逻辑
        register0(promise);
    } else {
        try {
            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);
        }
    }
}
private void register0(ChannelPromise promise) {
    try {
        // check if the channel is still open as it could be closed in the mean time when the register
        // call was outside of the eventLoop
        if (!promise.setUncancellable() || !ensureOpen(promise)) {
            return;
        }
        boolean firstRegistration = neverRegistered;
        // <1>交给子类来实现
        doRegister();
        // <2>设置标志位
        // 将从未注册标志位设置为false
        neverRegistered = false;
        // 将注册标志位设置为true
        registered = true;

        // Ensure we call handlerAdded(...) before we actually notify the promise. This is needed as the
        // user may already fire events through the pipeline in the ChannelFutureListener.
        pipeline.invokeHandlerAddedIfNeeded();

        safeSetSuccess(promise);
        // <3>触发channelRegistered事件
        pipeline.fireChannelRegistered();
        // Only fire a channelActive if the channel has never been registered. This prevents firing
        // multiple channel actives if the channel is deregistered and re-registered.
        // <4> 触发channelActive
        if (isActive()) {
            if (firstRegistration) {
                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);
    }
}

下面看下AbstractNioChannel的doRegsiter

protected void doRegister() throws Exception {
    boolean selected = false;
    for (;;) {
        try {
        	// 将当前channel注册到selector上,每个eventLoop独有一个selector
            selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
            return;
        } catch (CancelledKeyException e) {
            if (!selected) {
                // Force the Selector to select now as the "canceled" SelectionKey may still be
                // cached and not removed because no Select.select(..) operation was called yet.
                eventLoop().selectNow();
                selected = true;
            } else {
                // We forced a select operation on the selector before but the SelectionKey is still cached
                // for whatever reason. JDK bug ?
                throw e;
            }
        }
    }
}

在这里插入图片描述

具体bind操作

在这里插入图片描述
在这里插入图片描述
调用channel.bind,内部会调用当前channel所属的pipeline.bind,pipeline的类型是DefaultPipeline
DefaultPipeline.bind,内部会调用tailContext.bind,tailContext.bind会将bind传递到下一个ChannelOutboundHandler,最终传递给HeadContext,HeadContext.bind内部会调用unsafe.bind
下面具看下AbstractUnsafe.bind方法

public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
   // 确定在eventloop中
   assertEventLoop();

   // 省略部分代码
   boolean wasActive = isActive();
   try {
   		// 由具体子类来实现具体的绑定逻辑
       doBind(localAddress);
   } catch (Throwable t) {
       safeSetFailure(promise, t);
       closeIfClosed();
       return;
   }

   if (!wasActive && isActive()) {
   		// 向当前channel绑定的eventloop提交任务,任务会触发channelActive
       invokeLater(new Runnable() {
           @Override
           public void run() {
               pipeline.fireChannelActive();
           }
       });
   }

   safeSetSuccess(promise);
}

下面用一张图来说明bind过程中做了哪些操作
在这里插入图片描述

接收连接

在上面绑定到本地端口的过程中,最后触发了ChannelActive事件,然后会执行如下流程
在这里插入图片描述

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

看下AbstractNioChannel的实现

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

    readPending = true;

    final int interestOps = selectionKey.interestOps();
    /// readInterestOp是OP_ACCEPT
    if ((interestOps & readInterestOp) == 0) {
        selectionKey.interestOps(interestOps | readInterestOp);
    }
}

ServerBootstrap

init

下面看下ServerBootstrap是如何初始化新创建的channel的

void init(Channel channel) throws Exception {
	// <1> 将option设置到channel上
    final Map<ChannelOption<?>, Object> options = options0();
    synchronized (options) {
        setChannelOptions(channel, options, logger);
    }

	// <2> 将attr设置到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());
        }
    }

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

	// <3> 在channelPipeLine的最后新增一个ChannelInitializer
    p.addLast(new ChannelInitializer<Channel>() {
        @Override
        public void initChannel(final Channel ch) throws Exception {
            final ChannelPipeline pipeline = ch.pipeline();
            ChannelHandler handler = config.handler();
            // 将通过handler方法设置的handler添加到pipeline的最后
            if (handler != null) {
                pipeline.addLast(handler);
            }
			
			// 向channel绑定的eventloop提交任务,该任务会向channelPipeline添加一个ServerBootstrapAcceptor
			// ServerBootstrapAcceptor主要用来创建channel,将childHandler, childOptions, childAttrs等设置到channel上
			// 并且将channel设置到childEventLoop上
            ch.eventLoop().execute(new Runnable() {
                @Override
                public void run() {
                    pipeline.addLast(new ServerBootstrapAcceptor(
                            ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                }
            });
        }
    });
}

ServerBootstrapAcceptor

下面看下ServerBootstrapAcceptor的channelRead方法
将childHandler childOptions childAttrs等设置到channel上

public void channelRead(ChannelHandlerContext ctx, Object msg) {
    final Channel child = (Channel) msg;

    child.pipeline().addLast(childHandler);

    setChannelOptions(child, childOptions, logger);

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

    try {
        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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值