从NIO到netty(12)Channel注册逻辑

56 篇文章 2 订阅

回到AbstractBootstrap#initAndRegister方法

接着分析这句话

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

首先是调用config()方法,这里直接返回一个Serverbootstrap的成员变量

private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);

ServerBootstrapConfig封装了serverbootstrap的一些属性

public final class ServerBootstrapConfig extends AbstractBootstrapConfig<ServerBootstrap, ServerChannel> {

    ServerBootstrapConfig(ServerBootstrap bootstrap) {
        super(bootstrap);
    }

    /**
     * Returns the configured {@link EventLoopGroup} which will be used for the child channels or {@code null}
     * if non is configured yet.
     */
    @SuppressWarnings("deprecation")
    public EventLoopGroup childGroup() {
        return bootstrap.childGroup();
    }

    /**
     * Returns the configured {@link ChannelHandler} be used for the child channels or {@code null}
     * if non is configured yet.
     */
    public ChannelHandler childHandler() {
        return bootstrap.childHandler();
    }

    /**
     * Returns a copy of the configured options which will be used for the child channels.
     */
    public Map<ChannelOption<?>, Object> childOptions() {
        return bootstrap.childOptions();
    }

    /**
     * Returns a copy of the configured attributes which will be used for the child channels.
     */
    public Map<AttributeKey<?>, Object> childAttrs() {
        return bootstrap.childAttrs();
    }
}

回到initAndRegister

这里调用了config.group方法,这里将会返回

AbstractBootstrap中的group对象,也就是我们再代码中所写的bossgroup

接着调用register会进入

MultithreadEventLoopGroup#register方法
@Override
public ChannelFuture register(Channel channel) {
    return next().register(channel);
}

一直往下跟踪会进入

MultithreadEventExecutorGroup#next方法
@Override
public EventExecutor next() {
    return chooser.next();
}

这里出现了一个chooser

chooser是

MultithreadEventExecutorGroup中的一个成员变量
private final EventExecutorChooserFactory.EventExecutorChooser chooser;

具体的初始化是在

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                        EventExecutorChooserFactory chooserFactory, Object... args)方法中
chooser = chooserFactory.newChooser(children);

进入newChooser方法

/**
 * Default implementation which uses simple round-robin to choose next {@link EventExecutor}.
 * 默认使用round-robin算法选择下一个实例的EventExecutor实现
 * round-robin:主要用在负载均衡方向,比如有5台机器,第一次分请求到了第一台机器,第二次到了第二台机器,第三次请求到了第三台请求,以此类推一直到第五台机器,然后第六次又到了第一台机器,这样一个轮流的调用,处理负载,这里的Executor数组也是使用这种方式,保证数组里边的EventExecutor被均衡调用。
 */
public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {
    public EventExecutorChooser newChooser(EventExecutor[] executors) {
        if (isPowerOfTwo(executors.length)) {
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {
            return new GenericEventExecutorChooser(executors);
        }
    }
从这里可以看到netty对性能的压榨,当有2的指数个executor的时候使用PowerOfTwoEventExecutorChooser性能会比非指数个的GenericEventExecutorChooser性能高一点,PowerOfTwoEventExecutorChooser和GenericEventExecutorChooser都是DefaultEventExecutorChooserFactory 的静态内部类,都有next()方法返回一个EventExecutor。以上是对chooser的创建的一个分析, 
无论PowerOfTwoEventExecutorChooser还是GenericEventExecutorChooser的next方法都会返回一个

EventExecutor
public EventLoop next() {
    return (EventLoop) super.next();
}

返回一个EventExecutor之后并且强转成EventLoop

之后调用register会进入

SingleThreadEventLoop的register方法
@Override
public ChannelFuture register(Channel channel) {
    return register(new DefaultChannelPromise(channel, this));
}

这里首先会创建一个DefaultChannelPromise对象。DefaultChannelPromise是一个ChannelFuture的具体实现,持有channel和EventLoop的引用

最终会进入

@Override
public ChannelFuture register(final ChannelPromise promise) {
    ObjectUtil.checkNotNull(promise, "promise");
    promise.channel().unsafe().register(this, promise);
    return promise;
}

这里才是真正注册的逻辑

promise.channel().unsafe().register(this, promise)

首先通过promise获取到相应的channel随后调用channel中的unsafe方法获取到一个unsafe对象

进入AbstractChannel#中的内部类

AbstractUnsafe#register方法
  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);
        }
    }
}

核心方法是register0,这里要特别说明下为什么要分成if 和else,判断的条件就是eventLoop.inEventLoop()

 AbstractEventExecutor #inEventLoop
    public boolean inEventLoop() {
        return inEventLoop(Thread.currentThread());//参数为当前线程。
    }

----->

SingleThreadEventLoop#inEventLoop

public boolean inEventLoop(Thread thread) { return thread == this.thread; }

判断当前线程是不是SingleThreadEventExecutor里边维护的线程。所以else里边的逻辑是SingleThreadEventExecutor里边的线程不是当前线程的时候,新建一个Thread去执行register0,下边看一下register0

register0中核心方法是doRegister

AbstractNioChannel#doRegister

关键在这行代码

for (;;){

....

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

这个代码是不是很熟悉,我在最初的NIO例子中写的是channel.register(selector,SelectionKey.OP_CONNECT)

很类似的。

 

)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值