1.在NioSocketChannel里面直接从java的SelectorProvider里面拿到SelectorProvider
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
2.在创建NioSocketChannel的时候会创建一个, NioSocketChannel会把NioSocketChannel和socke传入
public NioSocketChannel(Channel parent, SocketChannel socket) {
super(parent, socket);
config = new NioSocketChannelConfig(this, socket.socket());
}
3.newUnsafe调用的是NioSocketChannel的newUnsafe方法,返回的是NioSocketChannelUnsafe的类
protected AbstractNioUnsafe newUnsafe() {
return new NioSocketChannelUnsafe();
}
4.newPipeline会把当前的NioSocketChannel传入进去
protected DefaultChannelPipeline newChannelPipeline() {
return new DefaultChannelPipeline(this);
}
在DefaultChannelPipeline里面会创建AbstractChannelHandlerContext 双向链表head和tail
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
tail = new TailContext(this);
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
head和tail里面传入的this是DefaultChannelPipeline
链表中 head 是一个 ChannelOutboundHandler, 而 tail 则是一个 ChannelInboundHandler.
接着看一下 HeadContext 的构造器:
HeadContext(DefaultChannelPipeline pipeline) {
super(pipeline, null, HEAD_NAME, false, true);
unsafe = pipeline.channel().unsafe();
}
----------
第二部分是NioEventLoopGroup
1.NioEventLoop 有几个重载的构造器, 不过内容都没有什么大的区别, 最终都是调用的父类MultithreadEventLoopGroup构造器:
protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
super(nThreads == 0? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);
}
在MultithreadEventLoopGroup里面定义
DEFAULT_EVENT_LOOP_THREADS是取cpu处理器的个数*2
private static final int DEFAULT_EVENT_LOOP_THREADS;
static {
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
if (logger.isDebugEnabled()) {
logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
}
}
2.在 MultithreadEventExecutorGroup里面定义EventExecutor数据 children,
EventExecutorChooserFactory.EventExecutorChooser chooser;
EventExecutorChooserFactory chooserFactory 是在
DefaultEventExecutorChooserFactory.INSTANCE 创建的
public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();
public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {
private final EventExecutor[] children;
private final Set<EventExecutor> readonlyChildren;
private final AtomicInteger terminatedChildren = new AtomicInteger();
private final Promise<?> terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
private final EventExecutorChooserFactory.EventExecutorChooser chooser;
在 MultithreadEventExecutorGroup构造函数中,创建 children = EventExecutor[nThreads];
主要做了两件事,对children的每一个元素创建一个newchild
第二是chooserFactory.newChooser方法创建一个EventExecutorChooser
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
children[i] = newChild(executor, args);
success = true;
}
}
chooser = chooserFactory.newChooser(children);
final FutureListener<Object> terminationListener = new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
}
}
};
for (EventExecutor e: children) {
e.terminationFuture().addListener(terminationListener);
}
Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
3.在 chooser = chooserFactory.newChooser(children); 实现方法
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
4.熟悉EventExcutor之前,要知道Excutor是线程池的老祖宗
ThreadPoolExecutor用来创建线程池的,都是通过攻击类Excutors来创建的
比如
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
EventExcutor是从ScheduledExecutorService里面派生出来的接口
public interface EventExecutorGroup extends ScheduledExecutorService, Iterable<EventExecutor>
5.在 children[i] = newChild(executor, args); 的时候,调用的是NIOEventLoopGroup的newChild方法
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
返回的是一个NioEventLoop对象,NIOEventLoopGroup是继承了SingleThreadEventLoop的
public final class NioEventLoop extends SingleThreadEventLoop
SinleThreadEventLoop 这个单线程池是实现了EventExcutor接口,还继承了 AbstractExecutorService
public abstract class AbstractEventExecutor extends AbstractExecutorService implements EventExecutor
AbstractExecutorService 就是线程池 ThreadPoolExecutor 的父类
6.总结
最后总结一下整个 EventLoopGroup 的初始化过程吧:
EventLoopGroup(其实是MultithreadEventExecutorGroup) 内部维护一个类型为 EventExecutor children 数组, 其大小是 nThreads, 这样就构成了一个线程池
如果我们在实例化 NioEventLoopGroup 时, 如果指定线程池大小, 则 nThreads 就是指定的值, 反之是处理器核心数 * 2
MultithreadEventExecutorGroup 中会调用 newChild 抽象方法来初始化 children 数组
抽象方法 newChild 是在 NioEventLoopGroup 中实现的, 它返回一个 NioEventLoop 实例.
NioEventLoop 属性:
SelectorProvider provider 属性: NioEventLoopGroup 构造器中通过 SelectorProvider.provider() 获取一个 SelectorProvider
Selector selector 属性: NioEventLoop 构造器中通过调用通过 selector = provider.openSelector() 获取一个 selector 对象.
-----------------
第三部分 channel的初始化和注册
1.channel注册是注入到selector里面的, 在bootStrap里面调用的
final ChannelFuture initAndRegister() {
Channel channel = null;
channel = channelFactory.newChannel();
init(channel);
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
2.在 ChannelFuture regFuture = config().group().register(channel);
config是BootStrap里面定义的, 然后把自己bootstrap当做参数传入进去的
private final BootstrapConfig config = new BootstrapConfig(this);
group方法就是返回的就是EventLoopGroup
public final EventLoopGroup group() {
return group;
}
register调用的是MultithreadEventLoopGroup类的,
他是NIOEventLoopGroup的父类, 你放在bootStrap里面的是NIOEventLoopGroup对象
public ChannelFuture register(Channel channel) {
return next().register(channel);
}
next方法是MultithreadEventExecutorGroup类的
public EventExecutor next() {
return chooser.next();
}
调用的是chooser的next方法, chooser是在 MultithreadEventExecutorGroup的构造函数中创建的
参数是children也就是EventExcutor数组,这个EventExcutor的实现类是NioEventLoop
NioEventLoop 是 SingleThreadEventLoop类的子类
chooser = chooserFactory.newChooser(children);
next方法最终的调用是PowerOfTwoEventExecutorChooser类或者是GenericEventExecutorChooser
PowerOfTwoEventExecutorChooser类的
public EventExecutor next() {
return executors[idx.getAndIncrement() & executors.length - 1];
}
GenericEventExecutorChooser类的
private static final class GenericEventExecutorChooser implements EventExecutorChooser {
@Override
public EventExecutor next() {
return executors[Math.abs(idx.getAndIncrement() % executors.length)];
}
}
每一次调用next方法,idx索引值都会自增,从0开始
register方法是在 SingleThreadEventLoop类的
public ChannelFuture register(Channel channel) {
return register(new DefaultChannelPromise(channel, this));
}
DefaultChannelPromise持有两个参数对象NioEventLoop和NioSocketChannel
channel是在BootStrap里面传入进去的NioSocketChannel类创建出来的实例
this 对象是NioEventLoop
new DefaultChannelPromise(channel, this);
public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
promise.channel().unsafe().register(this, promise);
return promise;
}
这个register是AbstractUnsafe的register,是从NioSocketChannel里面拿出来的
promise.channel().unsafe().register(this, promise);
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
if (eventLoop == null) {
throw new NullPointerException("eventLoop");
}
if (isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
if (!isCompatible(eventLoop)) {
promise.setFailure(
new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
return;
}
//上面这些都是抛异常的方法
AbstractChannel.this.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);
}
}
}
inEventLoop是判断当前的线程是否等于SingleThreadEventExecutor类的thread
public boolean inEventLoop() {
return inEventLoop(Thread.currentThread());
}
SingleThreadEventExecutor类的
public boolean inEventLoop(Thread thread) {
return thread == this.thread;
}
3.调用register0方法
DefaultChannelPromise持有两个参数对象NioEventLoop和NioSocketChannel
register0是AbstractUnsafe这个类的,
AbstractUnsafe.register0
但是它里面调用的doRegister方法是 AbstractChannel.doRegister() 的,就是回调方法
AbstractUnsafe是AbstractChannel的内部类
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;
doRegister();
neverRegistered = false;
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);
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.
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);
}
}
调用NioSocketChannel类的doRegister方法,这个是在他的父类 AbstractNioChannel
eventLoop()返回的是NioEventLoop对象,这个是在register方法里面注册的
AbstractChannel.this.eventLoop = eventLoop;
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
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;
}
}
}
}
javachannel是在创建NioSocketChannel的时候创建的SocketChannel
EventLoop().unwrappedSelector()从NioEventLoop里面,就是EventExcutor数组里面
也就是线程池里面取出selector
0是对任务事件都不感兴趣
this把NioSocketChannel当做附件
javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
总结:
我们总结一下 Channel 的注册过程:
首先在 AbstractBootstrap.initAndRegister中, 通过 group().register(channel), 调用 MultithreadEventLoopGroup.register 方法
在MultithreadEventLoopGroup.register 中, 通过 next() 获取一个可用的 SingleThreadEventLoop, 然后调用它的 register
在 SingleThreadEventLoop.register 中, 通过 channel.unsafe().register(this, promise) 来获取 channel 的 unsafe() 底层操作对象, 然后调用它的 register.
在 AbstractUnsafe.register 方法中, 调用 register0 方法注册 Channel
在 AbstractUnsafe.register0 中, 调用 AbstractNioChannel.doRegister 方法
AbstractNioChannel.doRegister 方法通过 javaChannel().register(eventLoop().selector, 0, this) 将 Channel 对应的 Java NIO SockerChannel 注册到一个 eventLoop 的 Selector 中, 并且将当前 Channel 作为 attachment.
总的来说, Channel 注册过程所做的工作就是将 Channel 与对应的 EventLoop 关联,
因此这也体现了, 在 Netty 中, 每个 Channel 都会关联一个特定的 EventLoop,
并且这个 Channel 中的所有 IO 操作都是在这个 EventLoop 中执行的; 当关联好 Channel 和 EventLoop 后,
会继续调用底层的 Java NIO SocketChannel 的 register 方法, 将底层的 Java NIO SocketChannel 注册到指定的 selector 中.
通过这两步, 就完成了 Netty Channel 的注册过程.
--------