nginx如何實(shí)現(xiàn)高并發(fā)

簡(jiǎn)單來講,就是異步,非阻塞,使用了epoll和大量的底層代碼優(yōu)化。

稍微詳細(xì)一點(diǎn)展開的話,就是nginx的特殊進(jìn)程模型和事件模型的設(shè)計(jì)。

nginx如何實(shí)現(xiàn)高并發(fā)

視頻課程推薦→:《千萬級(jí)數(shù)據(jù)并發(fā)解決方案(理論+實(shí)戰(zhàn))》

進(jìn)程模型

nginx采用一個(gè)master進(jìn)程,多個(gè)woker進(jìn)程的模式。

master進(jìn)程主要負(fù)責(zé)收集、分發(fā)請(qǐng)求。當(dāng)一個(gè)請(qǐng)求過來時(shí),master拉起一個(gè)worker進(jìn)程負(fù)責(zé)處理這個(gè)請(qǐng)求。

master進(jìn)程也要負(fù)責(zé)監(jiān)控woker的狀態(tài),保證高可靠性

woker進(jìn)程一般設(shè)置為跟cpu核心數(shù)一致。nginx的woker進(jìn)程跟apache不一樣。apche的進(jìn)程在同一時(shí)間只能處理一個(gè)請(qǐng)求,所以它會(huì)開很多個(gè)進(jìn)程,幾百甚至幾千個(gè)。而nginx的woker進(jìn)程在同一時(shí)間可以處理額請(qǐng)求數(shù)只受內(nèi)存限制,因此可以處理多個(gè)請(qǐng)求。

事件模型

nginx是異步非阻塞的。

每進(jìn)來一個(gè)request,會(huì)有一個(gè)worker進(jìn)程去處理。但不是全程的處理,處理到什么程度呢?處理到可能發(fā)生阻塞的地方,比如向上游(后端)服務(wù)器轉(zhuǎn)發(fā)request,并等待請(qǐng)求返回。那么,這個(gè)處理的worker不會(huì)這么傻等著,他會(huì)在發(fā)送完請(qǐng)求后,注冊(cè)一個(gè)事件:“如果upstream返回了,告訴我一聲,我再接著干”。于是他就休息去了。此時(shí),如果再有request 進(jìn)來,他就可以很快再按這種方式處理。而一旦上游服務(wù)器返回了,就會(huì)觸發(fā)這個(gè)事件,worker才會(huì)來接手,這個(gè)request才會(huì)接著往下走。

web server的工作性質(zhì)決定了每個(gè)request的大部份生命都是在網(wǎng)絡(luò)傳輸中,實(shí)際上花費(fèi)在server機(jī)器上的時(shí)間片不多。這是幾個(gè)進(jìn)程就解決高并發(fā)的秘密所在。

IO多路復(fù)用模型epoll

epoll() ,內(nèi)核維護(hù)一個(gè)鏈表,epoll_wait 直接檢查鏈表是不是空就知道是否有文件描述符準(zhǔn)備好了。內(nèi)核實(shí)現(xiàn)epoll 是根據(jù)每個(gè) sockfd 上面的與設(shè)備驅(qū)動(dòng)程序建立起來的 回調(diào)函數(shù) 實(shí)現(xiàn)的。那么,某個(gè) sockfd 上的事件發(fā)生時(shí),與它對(duì)應(yīng)的回調(diào)函數(shù)就會(huì)被調(diào)用,來把這個(gè) sockfd 加入鏈表,其他處于“空閑的”狀態(tài)的則不會(huì)。

select() ,內(nèi)核采用 輪訓(xùn) 的方法來查看是否有fd 準(zhǔn)備好,其中的保存 sockfd 的是類似數(shù)組的數(shù)據(jù)結(jié)構(gòu) fd_set,key 為 fd,value 為 0 或者 1。

poll()

【總結(jié)】:epoll 與 select 相比最大的優(yōu)點(diǎn)是不會(huì)隨著 sockfd 數(shù)目增長(zhǎng)而降低效率。

更多Nginx相關(guān)技術(shù)文章,請(qǐng)?jiān)L問Nginx使用教程欄目進(jìn)行學(xué)習(xí)!

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊12 分享