nginx架构初探
nginx是多進(jìn)程的架構(gòu),由master進(jìn)程和多個(gè)worker進(jìn)程組成。master進(jìn)程和worker進(jìn)程之間
用信號(hào)進(jìn)行通信。nginx默認(rèn)是以后臺(tái)進(jìn)程的形式運(yùn)行的。系統(tǒng)管理員通過信號(hào)與master進(jìn)程通信
進(jìn)而與worker進(jìn)程通信。同一個(gè)請(qǐng)求只會(huì)在一個(gè)worker進(jìn)程之間進(jìn)行處理。worker進(jìn)程的數(shù)目是
可以通過配置文件改變的。一般worker進(jìn)程的數(shù)目設(shè)置為cpu的核數(shù)。進(jìn)程越多并不代表性能越高,
因?yàn)椴僮飨到y(tǒng)在管理多進(jìn)程的時(shí)候還需要進(jìn)程的上下文切換,這個(gè)也是有時(shí)間消耗的。
?
?
1、nginx的信號(hào)處理
kill -HUP pid用于告訴nginx,從容地重啟nginx,我們一般用這個(gè)信號(hào)來重啟nginx,或重新加載配置,因?yàn)槭菑娜莸刂貑?#xff0c;因此服務(wù)是不中斷的。master進(jìn)程在接收到HUP信號(hào)后是怎么做的呢?首先master進(jìn)程在接到信號(hào)后,會(huì)先重新加載配置文件,然后再啟動(dòng)新的進(jìn)程,并向所有老的進(jìn)程發(fā)送信號(hào),告訴他們可以光榮退休了。新的進(jìn)程在啟動(dòng)后,就開始接收新的請(qǐng)求,而老的進(jìn)程在收到來自master的信號(hào)后,就不再接收新的請(qǐng)求,并且在當(dāng)前進(jìn)程中的所有未處理完的請(qǐng)求處理完成后,再退出。當(dāng)然,直接給master進(jìn)程發(fā)送信號(hào),這是比較老的操作方式,nginx在0.8版本之后,引入了一系列命令行參數(shù),來方便我們管理。比如,./nginx -s reload,就是來重啟nginx,./nginx -s stop,就是來停止nginx的運(yùn)行。如何做到的呢?我們還是拿reload來說,我們看到,執(zhí)行命令時(shí),我們是啟動(dòng)一個(gè)新的nginx進(jìn)程,而新的nginx進(jìn)程在解析到reload參數(shù)后,就知道我們的目的是控制nginx來重新加載配置文件了,它會(huì)向master進(jìn)程發(fā)送信號(hào),然后接下來的動(dòng)作,就和我們直接向master進(jìn)程發(fā)送信號(hào)一樣了。
2.nginx如何處理請(qǐng)求
每一個(gè)nginx的worker進(jìn)程都是平等的,都有同樣的機(jī)會(huì)獲得處理一個(gè)client請(qǐng)求的機(jī)會(huì),
nginx啟動(dòng)之后,master進(jìn)程會(huì)去監(jiān)聽80端口,worker進(jìn)程從master進(jìn)程fork出來之后,
子進(jìn)程繼承了父進(jìn)程打開的文件句柄,則子進(jìn)程同樣監(jiān)聽了80端口,每個(gè)請(qǐng)求來了之后
所有在accept在這個(gè)socket上面的進(jìn)程,都會(huì)收到通知,而只有一個(gè)進(jìn)程可以accept這個(gè)
連接,其它的則accept失敗,這是所謂的驚群現(xiàn)象。當(dāng)然,nginx也不會(huì)視而不見,所以
nginx提供了一個(gè)accept_mutex這個(gè)東西,從名字上,我們可以看這是一個(gè)加在accept上
的一把共享鎖。有了這把鎖之后,同一時(shí)刻,就只會(huì)有一個(gè)進(jìn)程在accpet連接,這樣就
不會(huì)有驚群?jiǎn)栴}了。accept_mutex是一個(gè)可控選項(xiàng),我們可以顯示地關(guān)掉,默認(rèn)是打開
的。當(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)程中處理。
nginx采用了異步非阻塞的方式來處理請(qǐng)求。nginx為了更好的利用多核特性,提供了cpu
親緣性的綁定選項(xiàng),我們可以將某一個(gè)進(jìn)程綁定在某一個(gè)核上,這樣就不會(huì)因?yàn)檫M(jìn)程的
切換帶來cache的失效。
nginx在做4個(gè)字節(jié)的字符串比較時(shí),會(huì)將4個(gè)字符轉(zhuǎn)換成一個(gè)int型,再作比較,以減少
cpu的指令數(shù)等等。
3. nginx的事件處理模型
對(duì)于一個(gè)基本的web服務(wù)器來說,事件通常有三種類型,網(wǎng)絡(luò)事件、信號(hào)、定時(shí)器。
?
while (true) {
??? for t in run_tasks:
??????? t.handler();
??? update_time(&now);
??? timeout = ETERNITY;
??? for t in wait_tasks: /* sorted already */
??????? if (t.time <= now) {
??????????? t.timeout_handler();
??????? } else {
??????????? timeout = t.time - now;
??????????? break;
??????? }
??? nevents = poll_function(events, timeout);
??? for i in nevents:
??????? task t;
??? if (events[i].type == READ) {
??????? t.handler = read_handler;
??? } else (events[i].type == WRITE) {
??????? t.handler = write_handler;
??? }
??? run_tasks_add(t);
}
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/flowly/archive/2013/04/06/3002789.html
總結(jié)
- 上一篇: 常用工具备忘(更新中)
- 下一篇: Essential Grouping高性