用搭配用戶態(tài)線程(協(xié)程/輕量級(jí)線程)性能極佳)
先理清兩個(gè)概念I(lǐng)O多路復(fù)用epoll/select內(nèi)核層面單一線程監(jiān)聽(tīng)上萬(wàn)連接解決「多連接多線程」的線程爆炸問(wèn)題用戶態(tài)線程協(xié)程、輕量級(jí)線程如Java虛擬線程、Go goroutine、libco切換邏輯不進(jìn)入操作系統(tǒng)內(nèi)核完全在用戶空間完成上下文切換。二者結(jié)合后形成雙重性能優(yōu)化核心原因分6點(diǎn)一、普通內(nèi)核線程的致命開(kāi)銷對(duì)比襯托優(yōu)勢(shì)傳統(tǒng)OS內(nèi)核線程Thread切換流程線程阻塞/時(shí)間片耗盡 → 觸發(fā)系統(tǒng)調(diào)用/時(shí)鐘中斷CPU切換內(nèi)核態(tài)保存全套硬件寄存器、頁(yè)表、PCBOS調(diào)度器選新線程恢復(fù)現(xiàn)場(chǎng)切回用戶態(tài)整個(gè)過(guò)程涉及用戶態(tài)?內(nèi)核態(tài)切換、PCB內(nèi)存讀寫(xiě)、CPU緩存失效一次切換微秒級(jí)開(kāi)銷上萬(wàn)線程頻繁切換CPU直接打滿。而用戶態(tài)線程切換全程不進(jìn)內(nèi)核僅保存少量自定義棧/局部變量無(wú)中斷、無(wú)系統(tǒng)調(diào)用切換納秒級(jí)開(kāi)銷相差幾十上百倍。二、IO多路復(fù)用天然適配用戶態(tài)線程的調(diào)度模型IO多路復(fù)用的工作模式線程大部分時(shí)間阻塞在epoll_wait內(nèi)核阻塞無(wú)事件時(shí)完全不占用CPU。結(jié)合用戶態(tài)線程后流程多個(gè)用戶態(tài)協(xié)程共享同一個(gè)OS內(nèi)核線程協(xié)程發(fā)起socket讀寫(xiě) → 調(diào)用epoll注冊(cè)fd主動(dòng)讓出執(zhí)行權(quán)內(nèi)核線程阻塞在epoll_wait等待IO就緒內(nèi)核通知有fd就緒喚醒內(nèi)核線程調(diào)度器在用戶態(tài)切換到對(duì)應(yīng)協(xié)程處理數(shù)據(jù)。關(guān)鍵所有IO等待交給內(nèi)核epoll線程空閑時(shí)直接阻塞在內(nèi)核不會(huì)出現(xiàn)協(xié)程空輪詢協(xié)程切換只在有IO事件時(shí)發(fā)生切換次數(shù)極少。三、內(nèi)存占用差距巨大能支撐超高并發(fā)連接OS內(nèi)核線程每個(gè)線程默認(rèn)分配MB級(jí)棧Linux默認(rèn)8MB1萬(wàn)線程就要占用80GB內(nèi)存機(jī)器直接OOM用戶態(tài)協(xié)程棧按需動(dòng)態(tài)擴(kuò)容初始僅幾KB上萬(wàn)協(xié)程內(nèi)存消耗僅幾十MBIO多路復(fù)用負(fù)責(zé)承載海量文件描述符用戶態(tài)線程負(fù)責(zé)輕量執(zhí)行業(yè)務(wù)邏輯二者疊加可以單機(jī)輕松支持十萬(wàn)、百萬(wàn)TCP長(zhǎng)連接網(wǎng)關(guān)、IM、RPC場(chǎng)景。四、規(guī)避昂貴的「系統(tǒng)調(diào)用上下文切換」雙重?fù)p耗如果只用IO多路復(fù)用、純內(nèi)核線程開(kāi)發(fā)多業(yè)務(wù)場(chǎng)景下需要?jiǎng)?chuàng)建多個(gè)OS線程處理就緒事件IO頻繁時(shí)會(huì)大量觸發(fā)線程搶占切換。用戶態(tài)線程把調(diào)度邏輯搬到用戶空間IO等待交給epoll一次內(nèi)核阻塞業(yè)務(wù)切換用戶態(tài)完成不觸發(fā)內(nèi)核調(diào)度大幅減少用戶態(tài)/內(nèi)核態(tài)往返次數(shù)CPU緩存命中率更高。五、無(wú)鎖調(diào)度并發(fā)處理成本更低內(nèi)核線程之間并發(fā)訪問(wèn)共享資源必須加互斥鎖鎖競(jìng)爭(zhēng)會(huì)頻繁觸發(fā)內(nèi)核阻塞同一OS線程上的所有用戶態(tài)協(xié)程是串行執(zhí)行不存在多核競(jìng)爭(zhēng)業(yè)務(wù)代碼可以大幅減少鎖使用只有協(xié)程主動(dòng)讓出CPUIO阻塞時(shí)才切換臨界區(qū)代碼執(zhí)行中途不會(huì)被強(qiáng)制搶占規(guī)避大量鎖開(kāi)銷。六、分層模型各司其職性能最大化組件負(fù)責(zé)工作優(yōu)勢(shì)IO多路復(fù)用(epoll)內(nèi)核批量監(jiān)聽(tīng)海量連接阻塞等待IO事件解決C10K萬(wàn)連接問(wèn)題無(wú)空輪詢用戶態(tài)線程(協(xié)程)業(yè)務(wù)邏輯執(zhí)行、用戶態(tài)輕量切換極低切換開(kāi)銷、極小內(nèi)存、無(wú)內(nèi)核調(diào)度損耗反面對(duì)比兩種差方案只用內(nèi)核線程不用IO多路復(fù)用BIO一連接一線程線程數(shù)量爆炸內(nèi)存切換開(kāi)銷拉滿并發(fā)上限極低。只用IO多路復(fù)用單線程同步處理Nginx單進(jìn)程模型所有業(yè)務(wù)串行執(zhí)行一旦某個(gè)業(yè)務(wù)有CPU密集操作會(huì)阻塞全部連接無(wú)法利用多核引入用戶態(tài)多協(xié)程后可在單內(nèi)核線程內(nèi)并發(fā)處理多個(gè)IO業(yè)務(wù)同時(shí)多內(nèi)核線程綁定多核充分利用CPU。一句話總結(jié)IO多路復(fù)用讓大量連接阻塞在內(nèi)核、避免空輪詢用戶態(tài)線程把線程切換放到用戶空間省去內(nèi)核中斷、PCB調(diào)度的巨大開(kāi)銷二者結(jié)合既支持百萬(wàn)級(jí)并發(fā)連接又擁有極低CPU、內(nèi)存損耗是高性能網(wǎng)絡(luò)服務(wù)的標(biāo)準(zhǔn)方案。