話不多說,先上圖

Master-Worker模式
1、Nginx 在啟動(dòng)后,會(huì)有一個(gè) master 進(jìn)程和多個(gè)相互獨(dú)立的 worker 進(jìn)程。
2、接收來自外界的信號(hào),向各worker進(jìn)程發(fā)送信號(hào),每個(gè)進(jìn)程都有可能來處理這個(gè)連接。
3、Master進(jìn)程能監(jiān)控Worker進(jìn)程的運(yùn)行狀態(tài),當(dāng) worker 進(jìn)程退出后(異常情況下),會(huì)自動(dòng)啟動(dòng)新的 worker 進(jìn)程。
accept_mutex
由于所有子進(jìn)程都繼承了父進(jìn)程的 sockfd,那么當(dāng)連接進(jìn)來時(shí),所有子進(jìn)程都將收到通知并“爭著”與它建立連接,這就叫“驚群現(xiàn)象”。大量的進(jìn)程被激活又掛起,只有一個(gè)進(jìn)程可以accept() 到這個(gè)連接,這當(dāng)然會(huì)消耗系統(tǒng)資源。Nginx 提供了一個(gè) accept_mutex 這個(gè)東西,這是一個(gè)加在accept上的一把共享鎖。即每個(gè) worker 進(jìn)程在執(zhí)行 accept 之前都需要先獲取鎖,獲取不到就放棄執(zhí)行 accept()。有了這把鎖之后,同一時(shí)刻,就只會(huì)有一個(gè)進(jìn)程去 accpet(),這樣就不會(huì)有驚群問題了。
當(dāng)一個(gè) worker 進(jìn)程在 accept() 這個(gè)連接之后,就開始讀取請(qǐng)求,解析請(qǐng)求,處理請(qǐng)求,產(chǎn)生數(shù)據(jù)后,再返回給客戶端,最后才斷開連接,完成一個(gè)完整的請(qǐng)求。一個(gè)請(qǐng)求,完全由 worker 進(jìn)程來處理,而且只能在一個(gè) worker 進(jìn)程中處理。
用進(jìn)程而不用線程的好處
1、節(jié)省鎖帶來的開銷。每個(gè) worker 進(jìn)程都是獨(dú)立的進(jìn)程,不共享資源,不需要加鎖。同時(shí)在編程以及問題查上時(shí),也會(huì)方便很多。
2、獨(dú)立進(jìn)程,減少風(fēng)險(xiǎn)。采用獨(dú)立的進(jìn)程,可以讓互相之間不會(huì)影響,一個(gè)進(jìn)程退出后,其它進(jìn)程還在工作,服務(wù)不會(huì)中斷,master 進(jìn)程則很快重新啟動(dòng)新的 worker 進(jìn)程。當(dāng)然,worker 進(jìn)程的也能發(fā)生意外退出。
IO多路復(fù)用
對(duì)于Nginx來講,一個(gè)進(jìn)程只有一個(gè)主線程,那么它是怎么實(shí)現(xiàn)高并發(fā)的呢
采用了IO多路復(fù)用的原理,通過異步非阻塞的事件處理機(jī)制,epoll模型,實(shí)現(xiàn)了輕量級(jí)和高并發(fā)。 關(guān)于IO多路復(fù)用和epoll模型的詳細(xì)解讀,可以移步到我的這篇文章 => IO多路復(fù)用的三種機(jī)制Select,Poll,Epoll
nginx是如何具體實(shí)現(xiàn)的呢,簡單來說:每進(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ā)的秘密所在。