服務(wù)端處理網(wǎng)絡(luò)請(qǐng)求的流程圖
主要步驟包括
①獲取請(qǐng)求數(shù)據(jù): 客戶端與服務(wù)器建立連接發(fā)出請(qǐng)求蛤育,服務(wù)器接受請(qǐng)求(1-3)
②構(gòu)建響應(yīng):在用戶空間處理客戶端請(qǐng)求道伟,直到構(gòu)建響應(yīng)完成(4)
③返回?cái)?shù)據(jù):將構(gòu)建好的響應(yīng)再通過內(nèi)核空間的網(wǎng)絡(luò)I/O發(fā)還給客戶端
所以,服務(wù)端有兩個(gè)關(guān)鍵點(diǎn)
①如何管理連接粹排,獲取輸入數(shù)據(jù)
②服務(wù)器如何處理請(qǐng)求
阻塞與非阻塞
阻塞:被調(diào)用方在收到請(qǐng)求到返回結(jié)果之前的這段時(shí)間,調(diào)用方將一直等待种远。
非阻塞:調(diào)用方可以去忙別的事
所以,阻塞與非阻塞顽耳,主要說的是調(diào)用方
同步處理與異步處理
同步:被調(diào)用方得到最終結(jié)果坠敷,才返回妙同。
異步:被調(diào)用方先返回應(yīng)答,然后在計(jì)算結(jié)果膝迎,計(jì)算完最終結(jié)果再通知并返回粥帚。
所以,同步與異步,主要說的是被調(diào)用方
優(yōu)點(diǎn):在阻塞等待數(shù)據(jù)期間,進(jìn)程/線程掛起,基本不會(huì)占用CPU資源
缺點(diǎn):每個(gè)連接需要單獨(dú)的線程/進(jìn)程單獨(dú)處理,并發(fā)大時(shí)線程切換開銷大
優(yōu)點(diǎn):不會(huì)阻塞在內(nèi)核等待數(shù)據(jù),每次可以立馬返回限次,實(shí)時(shí)性較好
缺點(diǎn):會(huì)占用大量的CPU時(shí)間茎辐,系統(tǒng)資源利用率低
之前我們的I/O阻塞模型不是會(huì)創(chuàng)建大量連接?那現(xiàn)在我們就先注冊(cè)到select上,讓select有數(shù)據(jù)了再通知我們掂恕。
優(yōu)點(diǎn):可以基于一個(gè)阻塞對(duì)象,同時(shí)在多個(gè)描述符上進(jìn)行等待就緒弛槐,而不是使用多個(gè)線程懊亡。
缺點(diǎn):連接數(shù)較少時(shí)效率相比多線程+阻塞I/O模型,效率較低,延時(shí)會(huì)更大乎串。因?yàn)閱蝹€(gè)連接處理要經(jīng)過2次系統(tǒng)調(diào)用店枣,占用時(shí)間會(huì)增加
線程模型
Reactor模型
針對(duì)阻塞I/O模型進(jìn)行了改進(jìn)
①基于I/O復(fù)用模型,多個(gè)連接共用一個(gè)阻塞對(duì)象叹誉,應(yīng)用程序只需要在一個(gè)阻塞對(duì)象上等待鸯两,無需等待所有連接。
②基于線程池復(fù)用線程資源长豁,不必再為每個(gè)連接創(chuàng)建線程钧唐,將連接完成后的業(yè)務(wù)處理任務(wù)分配給線程進(jìn)行處理,一個(gè)線程可以處理多個(gè)連接的業(yè)務(wù)匠襟。
Reactor模式也叫Dispatcher模式钝侠,即I/O多了復(fù)用同一監(jiān)聽事件,收到事件后進(jìn)行分發(fā)
Reactor模式中的兩個(gè)關(guān)鍵組成
①Reactor酸舍,在單獨(dú)的線程中運(yùn)行帅韧,負(fù)責(zé)監(jiān)聽和分發(fā)事件,分發(fā)給適當(dāng)?shù)奶幚沓绦騺韺?duì)I/O事件做出反應(yīng)啃勉。
②Handlers,處理程序執(zhí)行I/O事件要完成的實(shí)際事件忽舟。
根據(jù)Reactor的數(shù)量和處理資源池線程的數(shù)量不同。
有3中典型實(shí)現(xiàn):
①單Reactor單線程
②單Reactor多線程
③主從Reactor多線程
單Reactor單線程
說明:
①Reactor對(duì)象通過select監(jiān)聽客戶端請(qǐng)求時(shí)間淮阐,收到事件后通過dispatch進(jìn)行分發(fā)
②建立連接請(qǐng)求事件叮阅,則由Acceptor通過accept處理連接請(qǐng)求,然后創(chuàng)建Handler對(duì)象處理連接完成后的后續(xù)業(yè)務(wù)處理
③如果不是連接事件泣特,則Reactor會(huì)分發(fā)調(diào)用連接對(duì)應(yīng)的Handler來相應(yīng)
④Handler會(huì)完成read->業(yè)務(wù)處理->send的完整業(yè)務(wù)流程
優(yōu)點(diǎn):簡(jiǎn)單明了帘饶,沒有多線程競(jìng)爭(zhēng)
缺點(diǎn):
性能問題:只有一個(gè)線程,無法發(fā)揮多線程的優(yōu)勢(shì)
可靠性問題:線程死了群扶,會(huì)導(dǎo)致整個(gè)通信模塊不可用及刻。
使用場(chǎng)景:客戶端數(shù)量有限镀裤,業(yè)務(wù)處理非常快速缴饭,如Redis
單Reactor多線程
①Reactor對(duì)象通過select監(jiān)聽客戶端請(qǐng)求時(shí)間暑劝,收到事件后通過dispatch進(jìn)行分發(fā)
②建立連接請(qǐng)求事件,則由Acceptor通過accept處理連接請(qǐng)求颗搂,然后創(chuàng)建Handler對(duì)象處理連接完成后的后續(xù)業(yè)務(wù)處理
③如果不是連接事件担猛,則Reactor會(huì)分發(fā)調(diào)用連接對(duì)應(yīng)的Handler來相應(yīng)
④Handler只負(fù)責(zé)響應(yīng)事件,不做業(yè)務(wù)處理,通過read讀取數(shù)據(jù)后丢氢,分發(fā)給后面的Worker線程池進(jìn)行業(yè)務(wù)處理
⑤Worker線程池分配獨(dú)立的線程完成真正的業(yè)務(wù)處理
⑥Handler收到響應(yīng)結(jié)果后通過send將結(jié)果返回給client
優(yōu)點(diǎn):可以充分利用多核CPU
缺點(diǎn):Reactor在高并發(fā)下容易成為性能瓶頸
主從Reactor多線程
①Reactor主線程MainReactor對(duì)象通過select監(jiān)聽客戶端請(qǐng)求時(shí)間傅联,收到事件后由Acceptor通過accept處理連接請(qǐng)求,建立連接請(qǐng)求事件
②Acceptor處理建立連接事件后,MainReactor將連接分配給SubReactor進(jìn)行處理
③SubReactor將連接加入到連接隊(duì)列進(jìn)行監(jiān)聽疚察,并創(chuàng)建一個(gè)Handler用于處理連接事件
④當(dāng)新事件發(fā)生時(shí)蒸走,SubReactor會(huì)調(diào)用連接對(duì)應(yīng)的Handler進(jìn)行響應(yīng)。
⑤Handler只負(fù)責(zé)響應(yīng)事件,不做業(yè)務(wù)處理貌嫡,通過read讀取數(shù)據(jù)后比驻,分發(fā)給后面的Worker線程池進(jìn)行業(yè)務(wù)處理
⑥Worker線程池分配獨(dú)立的線程完成真正的業(yè)務(wù)處理
⑦Handler收到響應(yīng)結(jié)果后通過send將結(jié)果返回給client
優(yōu)點(diǎn):父線程與子線程數(shù)據(jù)交互簡(jiǎn)單,職責(zé)明確岛抄,父線程只需要接收新連接别惦,子線程完成后續(xù)的業(yè)務(wù)處理
使用場(chǎng)景:Ngnix主從多進(jìn)程模型,Netty主從多線程模型