回到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)
很类似的。
)