我們在研究Netty對channel的註冊實現時
ChannelFuture regFuture = config().group().register(channel);
其中config()方法返回ServerBootstrapConfig對象,其中帶有ServerBootstrap的引用。
private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);
其中的group()方法返回賦值在ServerBootstrap的group屬性上的NioEventLoopGroup對象。
/**
* Returns the configured {@link EventLoopGroup} or {@code null} if non is configured yet.
*/
@SuppressWarnings("deprecation")
public final EventLoopGroup group() {
return bootstrap.group();
}
其中register()開始了正在的註冊過程,調用的是NioEventLoopGroup對象的register方法。
@Override
public ChannelFuture register(Channel channel) {
return next().register(channel);
}
其中next()方法會返回一個EventLoop對象,它是在NioEventLoopGroup的父類MultithreadEventLoopGroup中被調用的。
public EventLoop next() {
return (EventLoop) super.next();
其中又調用了MultithreadEventLoopGroup的父類MultithreadEventExecutorGroup中的next方法
@Override
public EventExecutor next() {
return chooser.next();
}
而我們使用的chooser又是什麼呢?他是一個EventExecutorChooser,被chooser工廠創建。在初始化NioEventLoopGroup的時候被初始化賦值。
chooser = chooserFactory.newChooser(children);
那我們的chooserFactory又是什麼呢?
根據我們在初始化NioEventLoopGroup的過程中,頻繁的調用父類的一些構造方法就已經被創建了。
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}
可以看出,他是DefaultEventExecutorChooserFactory的靜態成員變量,內部就是一個實例而已。
public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();
所以回到我們的chooserFactory.newChooser(children)方法
@SuppressWarnings("unchecked")
@Override
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
這會根據傳入參數的長度進行判斷,如果是二的指數值的話,就會選擇一個PowerOfTwoEventExecutorChooser實例,反之亦然。這兩個類其實就是一個負載均衡的簡單算法,採用輪詢的方式。
private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors;
PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override
public EventExecutor next() {
//取模-1
return executors[idx.getAndIncrement() & executors.length - 1];
}
}
我們傳入的參數executors是什麼呢?在上面可以看出在初始化NioEventLoopGroup的過程中會傳入children,這個就是它的參數。
而children又是什麼呢?
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}
if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
children[i] = newChild(executor, args);
可以看出,children是一個EventExecutor的數組,這個數組的長度是傳入的線程數量,裏面的值是EventLoopGroup的newChild方法返回的實例。
因爲我們當時是初始化NioEventLoopGroup,所以newChild方法就存在於MultithreadEventExecutorGroup的子類NioEventLoopGroup當中。
@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
總結:至此我們可以看出最開始的next方法返回的是一個NioEventLoop,所以隨後調用的register方法也是NioEventLooop的register方法。在其父類SingleThreadEventLoop中找到:
@Override
public ChannelFuture register(Channel channel) {
return register(new DefaultChannelPromise(channel, this));
}
@Override
public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
promise.channel().unsafe().register(this, promise);
return promise;
}
其中channel()返回當初傳入的channel,
其中unsafe()返回初始化channel時創建的unsafe屬性,是一個NioMessageUnsafe實例。
所以register方法就是可以定位到這個實例上了,而這個register方法真正的實現卻在它的父類AbstractUnsafe上,
@Override
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() {//執行下面的代碼,因爲eventloop本身也是一個執行器,所以會執行啓動一個線程取執行任務
@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);
}
}
}
這個execute方法在NioEventLoop的父類SingleThreadEventExecutor當中
@Override
public void execute(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
boolean inEventLoop = inEventLoop();
if (inEventLoop) {
addTask(task);
} else {
startThread();
addTask(task);
if (isShutdown() && removeTask(task)) {
reject();
}
}
if (!addTaskWakesUp && wakesUpForTask(task)) {
wakeup(inEventLoop);
}
}
private void startThread() {
if (state == ST_NOT_STARTED) {
if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
doStartThread();
}
}
}
private void doStartThread() {
assert thread == null;
executor.execute(new Runnable() {
//executor爲我們在初始化eventloop時傳入的一個excutor,類型爲ThreadPerTaskExecutor,一個任務一個線程的執行器
//裏面有一個線程工廠,會利用線程工廠創建一個線程,然後啓動線程,執行傳入的任務。
@Override
public void run() {
thread = Thread.currentThread();
if (interrupted) {
thread.interrupt();
}
boolean success = false;
updateLastExecutionTime();
try {
SingleThreadEventExecutor.this.run();//執行這個eventloop的run方法,
success = true;
} catch (Throwable t) {
logger.warn("Unexpected exception from an event executor: ", t);
} finally {
for (;;) {
int oldState = state;
if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
break;
}
}
// Check if confirmShutdown() was called at the end of the loop.
if (success && gracefulShutdownStartTime == 0) {
logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must be called " +
"before run() implementation terminates.");
}
try {
// Run all remaining tasks and shutdown hooks.
for (;;) {
if (confirmShutdown()) {
break;
}
}
} finally {
try {
cleanup();
} finally {
STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
threadLock.release();
if (!taskQueue.isEmpty()) {
logger.warn(
"An event executor terminated with " +
"non-empty task queue (" + taskQueue.size() + ')');
}
terminationFuture.setSuccess(null);
}
}
}
}
});
}
protected void run() {
for (;;) {
try {
switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
case SelectStrategy.CONTINUE:
continue;
case SelectStrategy.SELECT:
select(wakenUp.getAndSet(false));
default:
}
cancelledKeys = 0;
needsToSelectAgain = false;
final int ioRatio = this.ioRatio;
if (ioRatio == 100) {
try {
processSelectedKeys();//處理Slectedkey,看到希望了
} finally {
// Ensure we always run tasks.
runAllTasks();
}
} else {
final long ioStartTime = System.nanoTime();
try {
processSelectedKeys();
} finally {
// Ensure we always run tasks.
final long ioTime = System.nanoTime() - ioStartTime;
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);//運行所有的任務
}
}
} catch (Throwable t) {
handleLoopException(t);
}
// Always handle shutdown even if the loop processing threw an exception.
try {
if (isShuttingDown()) {
closeAll();
if (confirmShutdown()) {
return;
}
}
} catch (Throwable t) {
handleLoopException(t);
}
}
}
private void processSelectedKeys() {
if (selectedKeys != null) {//原本就沒有selectedKeys,爲空
processSelectedKeysOptimized();
} else {
processSelectedKeysPlain(selector.selectedKeys());//空
}
}
private void processSelectedKeysPlain(Set<SelectionKey> selectedKeys) {
// check if the set is empty and if so just return to not create garbage by
// creating a new Iterator every time even if there is nothing to process.
// See https://github.com/netty/netty/issues/597
if (selectedKeys.isEmpty()) {
return;//返回
}
Iterator<SelectionKey> i = selectedKeys.iterator();
for (;;) {
final SelectionKey k = i.next();
final Object a = k.attachment();
i.remove();
if (a instanceof AbstractNioChannel) {
processSelectedKey(k, (AbstractNioChannel) a);
} else {
@SuppressWarnings("unchecked")
NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
processSelectedKey(k, task);
}
if (!i.hasNext()) {
break;
}
if (needsToSelectAgain) {
selectAgain();
selectedKeys = selector.selectedKeys();
// Create the iterator again to avoid ConcurrentModificationException
if (selectedKeys.isEmpty()) {
break;
} else {
i = selectedKeys.iterator();
}
}
}
}
protected boolean runAllTasks(long timeoutNanos) {
fetchFromScheduledTaskQueue();
Runnable task = pollTask();
if (task == null) {
afterRunningAllTasks();
return false;
}
final long deadline = ScheduledFutureTask.nanoTime() + timeoutNanos;
long runTasks = 0;
long lastExecutionTime;
for (;;) {
safeExecute(task);
runTasks ++;
// Check timeout every 64 tasks because nanoTime() is relatively expensive.
// XXX: Hard-coded value - will make it configurable if it is really a problem.
if ((runTasks & 0x3F) == 0) {
lastExecutionTime = ScheduledFutureTask.nanoTime();
if (lastExecutionTime >= deadline) {
break;
}
}
task = pollTask();
if (task == null) {
lastExecutionTime = ScheduledFutureTask.nanoTime();
break;
}
}
afterRunningAllTasks();
this.lastExecutionTime = lastExecutionTime;
return true;
}
protected void addTask(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
if (!offerTask(task)) {
reject(task);
}
}
final boolean offerTask(Runnable task) {
if (isShutdown()) {
reject();
}
return taskQueue.offer(task);
}