1.Reactor單線程模型
傳統(tǒng)的javaNIO通信的線程模型甸各。該線程模型僅有一個(gè)I/O線程處理所有的I/O操作姑曙,如下圖:
所有的客戶端都連接到一個(gè)I/O線程負(fù)責(zé)的Acceptor上,連接成功后,由Reactor里的Dispatch將接收的ByteBuffer分發(fā)到指定的Handler上處理,進(jìn)行解碼,業(yè)務(wù)處理充蓝,編碼及發(fā)送給客戶端等過程。整個(gè)過程I/O線程都是異步非阻塞方式實(shí)現(xiàn)喉磁。
I/O線程完成的工作:
1)服務(wù)端NIO線程用于監(jiān)聽客戶端連接
2)客戶端NIO線程用于向服務(wù)器端發(fā)送連接請(qǐng)求
3)客戶端和服務(wù)端的讀寫操作
不足:
1)如果客戶端同時(shí)有成百上千的請(qǐng)求谓苟,會(huì)導(dǎo)致I/O線程不停的工作,CPU利用率負(fù)荷超載协怒,同時(shí)造成很多客戶端超時(shí)得不到響應(yīng)
2)一旦I/O線程出現(xiàn)異常涝焙,可能會(huì)導(dǎo)致所有客戶端掉線,造成系統(tǒng)單點(diǎn)故障
2.多線程的Reactor模型
多線程模型采用1個(gè)線程接收客戶端請(qǐng)求孕暇,同時(shí)使用1個(gè)線程池處理讀寫等操作仑撞。模型如下:
其中Acceptor單線程用于監(jiān)聽及接收client的連接請(qǐng)求,連接成功后會(huì)將這些連接注冊(cè)到WorkThreadPool(工作線程池)的其中一個(gè)線程上妖滔,由工作線程池分出1個(gè)工作線程用于和該client的讀寫隧哮、編碼、解碼操作座舍。一個(gè)client只能和一個(gè)工作線程對(duì)應(yīng)沮翔,不能注冊(cè)到多個(gè)工作線程,防止出現(xiàn)并發(fā)操作問題曲秉。
WorkThreadPool由一個(gè)任務(wù)隊(duì)列和N個(gè)線程組成采蚀,client連接成功后的讀寫請(qǐng)求都會(huì)放到任務(wù)隊(duì)列中,工作線程池會(huì)從任務(wù)隊(duì)列中獲取任務(wù)承二、分配線程進(jìn)行處理搏存。
注意:這里的工作線程并不是業(yè)務(wù)處理線程,工作線程只是負(fù)責(zé)業(yè)務(wù)線程處理前或者業(yè)務(wù)線程處理后的讀寫和編解碼操作矢洲。比如解碼成功后獲取對(duì)應(yīng)的消息內(nèi)容后璧眠,對(duì)這些消息的處理是由單獨(dú)的業(yè)務(wù)線程處理的,當(dāng)然業(yè)務(wù)線程一般也是有自己的線程池。
不足:?jiǎn)为?dú)的Acceptor線程會(huì)成為系統(tǒng)的瓶頸责静,一旦出現(xiàn)問題袁滥,后面的工作線程池也無法工作。
3.主從Reactor模型
該模型是的Acceptor由一個(gè)線程池MainReactorThreadPool負(fù)責(zé)監(jiān)聽和接收client的連接灾螃、認(rèn)證等题翻,同時(shí)由另一個(gè)SubReactorThreadPool線程池負(fù)責(zé)讀寫、編碼等工作腰鬼。模型如下:
該模型可以有效解決Acceptor單線程瓶頸問題嵌赠,同時(shí)能提高客戶端并發(fā)能力,穩(wěn)定性和處理效率高熄赡。
Netty支持上面三種不同的線程模型姜挺,針對(duì)不同的業(yè)務(wù)需求可以設(shè)置不同的啟動(dòng)參數(shù),選擇對(duì)應(yīng)的線程模型彼硫,不過netty官網(wǎng)推薦使用第三種主從模式炊豪。