Nginx的accept_mutex配置分析
通常多數(shù)人不會(huì)注意Nginx的accept_mutex配置,不過(guò)實(shí)際上它對(duì)系統(tǒng)的吞吐量有一定的影響,今天生物鐘紊亂睡不著覺(jué),索性閑扯一下Nginx的accept_mutex配置。
讓我們看看accept_mutex的意義:當(dāng)一個(gè)新連接到達(dá)時(shí),如果激活了accept_mutex,那么多個(gè)Worker將以串行方式來(lái)處理,其中有一個(gè)Worker會(huì)被喚醒,其他的Worker繼續(xù)保持休眠狀態(tài);如果沒(méi)有激活accept_mutex,那么所有的Worker都會(huì)被喚醒,不過(guò)只有一個(gè)Worker能獲取新連接,其它的Worker會(huì)重新進(jìn)入休眠狀態(tài),這就是「驚群?jiǎn)栴}」。
Nginx缺省激活了accept_mutex,也就是說(shuō)不會(huì)有驚群?jiǎn)栴},但真的有那么嚴(yán)重么?實(shí)際上Nginx作者Igor Sysoev曾經(jīng)給過(guò)相關(guān)的解釋:
OS may wake all processes waiting on accept() and select(), this is called thundering herd problem. This is a problem if you have a lot of workers as in Apache (hundreds and more), but this insensible if you have just several workers as nginx usually has. Therefore turning accept_mutex off is as scheduling incoming connection by OS via select/kqueue/epoll/etc (but not accept()).
簡(jiǎn)單點(diǎn)說(shuō):Apache動(dòng)輒就會(huì)啟動(dòng)成百上千的進(jìn)程,如果發(fā)生驚群?jiǎn)栴}的話,影響相對(duì)較大;但是對(duì)Nginx而言,一般來(lái)說(shuō),worker_processes會(huì)設(shè)置成CPU個(gè)數(shù),所以最多也就幾十個(gè),即便發(fā)生驚群?jiǎn)栴}的話,影響相對(duì)也較小。
…
假設(shè)你養(yǎng)了一百只小雞,現(xiàn)在你有一粒糧食,那么有兩種喂食方法:
- 你把這粒糧食直接扔到小雞中間,一百只小雞一起上來(lái)?yè)專罱K只有一只小雞能得手,其它九十九只小雞只能鎩羽而歸。這就相當(dāng)于關(guān)閉了accept_mutex。
- 你主動(dòng)抓一只小雞過(guò)來(lái),把這粒糧食塞到它嘴里,其它九十九只小雞對(duì)此渾然不知,該睡覺(jué)睡覺(jué)。這就相當(dāng)于激活了accept_mutex。
可以看到此場(chǎng)景下,激活accept_mutex相對(duì)更好一些,讓我們修改一下問(wèn)題的場(chǎng)景,我不再只有一粒糧食,而是一盆糧食,怎么辦?
此時(shí)如果仍然采用主動(dòng)抓小雞過(guò)來(lái)塞糧食的做法就太低效了,一盆糧食不知何年何月才能喂完,大家可以設(shè)想一下幾十只小雞排隊(duì)等著喂食時(shí)那種翹首以盼的情景。此時(shí)更好的方法是把這盆糧食直接撒到小雞中間,讓它們自己去搶,雖然這可能會(huì)造成一定程度的混亂,但是整體的效率無(wú)疑大大增強(qiáng)了。
…
Nginx缺省激活了accept_mutex,是一種保守的選擇。如果關(guān)閉了它,可能會(huì)引起一定程度的驚群?jiǎn)栴},表現(xiàn)為上下文切換增多(sar -w)或者負(fù)載上升,但是如果你的網(wǎng)站訪問(wèn)量比較大,為了系統(tǒng)的吞吐量,我還是建議大家關(guān)閉它。