1. Nio初始化階段
-
1.1 NioEndpoint 實(shí)現(xiàn)了建立連接、處理連接、和關(guān)閉連接等操作,在看NioEndpoint之前先看一下下面的uml圖
image.png
以上圖把整個(gè)NioEndpoint的核心關(guān)系展示出來了,我們?cè)诳聪聢Dtomcat中 nio的網(wǎng)絡(luò)模型借用了網(wǎng)上的圖片
image.png 1.2 acceptor 顧名思義用來處理鏈接 我們來看一下他在NioEndpoint中的實(shí)現(xiàn)
/**
* Start the NIO endpoint, creating acceptor, poller threads.
*/
@Override
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
//申請(qǐng)nioChannel 默認(rèn)128個(gè) 為什么有這個(gè)東西
//其實(shí)這個(gè)東西就是申請(qǐng)了系統(tǒng)內(nèi)存io讀寫直接使用系統(tǒng)內(nèi)存的效率比堆內(nèi)存好快很多
//當(dāng)然申請(qǐng)系統(tǒng)內(nèi)存會(huì)有很大的開銷,所以直接初始一些出來,這樣要用的時(shí)候直接可以使用、當(dāng)socket關(guān)閉的時(shí)候、nioChannel并不會(huì)被銷毀、而是重新放入這個(gè)隊(duì)列中、重復(fù)被使用
//總之可以理解內(nèi)核復(fù)用技術(shù)、類似netty的內(nèi)核復(fù)用技術(shù)
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());
if ( getExecutor() == null ) {
//構(gòu)建線程池對(duì)應(yīng)上圖的executor 它是用來處理SocketProcessor
//換句話主要是用來對(duì)socket進(jìn)行讀寫封裝成request對(duì)象然后做業(yè)務(wù)處理
//我們常常用的controller也是使用這個(gè)線程來執(zhí)行的
createExecutor();
}
initializeConnectionLatch();
// Start poller threads
// 初始化poller默認(rèn)是兩個(gè)poller
// poller主要循環(huán)掃描PollerEvent隊(duì)列是否存在待處理請(qǐng)求
// 如果存在PollerEvent待處理,進(jìn)行請(qǐng)求解析封裝
// 啟動(dòng)Executor線程進(jìn)行請(qǐng)求讀處理
pollers = new Poller[getPollerThreadCount()];
for (int i=0; i<pollers.length; i++) {
pollers[i] = new Poller();
Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
}
//啟動(dòng)Acceptor 默認(rèn)使用一單線程處理連接
startAcceptorThreads();
}
}
來看一下startAcceptorThreads的源碼
protected final void startAcceptorThreads() {
//acceptor連接池個(gè)數(shù) 默認(rèn)為一個(gè)
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];
for (int i = 0; i < count; i++) {
acceptors[i] = createAcceptor();
String threadName = getName() + "-Acceptor-" + i;
acceptors[i].setThreadName(threadName);
Thread t = new Thread(acceptors[i], threadName);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
}
以上就是Accetor、poller、Executor等核心組件初始化的過程