Nginx為什么比Apache Httpd高效:原理篇【轉(zhuǎn)】

Nginx才短短幾年,就拿下了web服務(wù)器大筆江山姜盈,眾所周知低千,Nginx在處理大并發(fā)靜態(tài)請(qǐng)求方面,效率明顯高于httpd馏颂,甚至能輕松解決C10K問(wèn)題示血。下面我們就來(lái)聊聊Web服務(wù)器背后的一些原理。

一救拉、進(jìn)程难审、線程?

進(jìn)程是具有一定獨(dú)立功能的亿絮,在計(jì)算機(jī)中已經(jīng)運(yùn)行的程序的實(shí)體告喊。在早期系統(tǒng)中(如linux 2.4以前),進(jìn)程是基本運(yùn)作單位壹无,在支持線程的系統(tǒng)中(如windows葱绒,linux2.6)中,線程才是基本的運(yùn)作單位斗锭,而進(jìn)程只是線程的容器地淀。程序本身只是指令、數(shù)據(jù)及其組織形式的描述岖是,進(jìn)程才是程序(那些指令和數(shù)據(jù))的真正運(yùn)行實(shí)例帮毁。若干進(jìn)程有可能與同一個(gè)程序相關(guān)系,且每個(gè)進(jìn)程皆可以同步(循序)或異步(平行)的方式獨(dú)立運(yùn)行〔虺牛現(xiàn)代計(jì)算機(jī)系統(tǒng)可在同一段時(shí)間內(nèi)以進(jìn)程的形式將多個(gè)程序加載到存儲(chǔ)器中烈疚,并借由時(shí)間共享(或稱時(shí)分復(fù)用),以在一個(gè)處理器上表現(xiàn)出同時(shí)(平行性)運(yùn)行的感覺(jué)聪轿。同樣的爷肝,使用多線程技術(shù)(多線程即每一個(gè)線程都代表一個(gè)進(jìn)程內(nèi)的一個(gè)獨(dú)立執(zhí)行上下文)的操作系統(tǒng)或計(jì)算機(jī)架構(gòu),同樣程序的平行線程陆错,可在多 CPU 主機(jī)或網(wǎng)絡(luò)上真正同時(shí)運(yùn)行(在不同的CPU上)灯抛。

二、常見(jiàn)Web服務(wù)方式

2.1 三種工作模型比較:

Web服務(wù)器要為用戶提供服務(wù)音瓷,必須以某種方式对嚼,工作在某個(gè)套接字上。一般Web服務(wù)器在處理用戶請(qǐng)求是绳慎,一般有如下三種方式可選擇:多進(jìn)程方式纵竖、多線程方式漠烧、異步方式。

多進(jìn)程方式:為每個(gè)請(qǐng)求啟動(dòng)一個(gè)進(jìn)程來(lái)處理靡砌。由于在操作系統(tǒng)中已脓,生成進(jìn)程、銷毀進(jìn)程通殃、進(jìn)程間切換都很消耗CPU和內(nèi)存摆舟,當(dāng)負(fù)載高是,性能會(huì)明顯降低邓了。

優(yōu)點(diǎn): 穩(wěn)定性!由于采用獨(dú)立進(jìn)程處理獨(dú)立請(qǐng)求媳瞪,而進(jìn)程之間是獨(dú)立的骗炉,單個(gè)進(jìn)程問(wèn)題不會(huì)影響其他進(jìn)程,因此穩(wěn)定性最好蛇受。

缺點(diǎn): 資源占用句葵!當(dāng)請(qǐng)求過(guò)大時(shí),需要大量的進(jìn)程處理請(qǐng)求兢仰,進(jìn)程生成乍丈、切換開(kāi)銷很大,而且進(jìn)程間資源是獨(dú)立的把将,造成內(nèi)存重復(fù)利用轻专。

多線程方式:一個(gè)進(jìn)程中用多個(gè)線程處理用戶請(qǐng)求。由于線程開(kāi)銷明顯小于進(jìn)程察蹲,而且部分資源還可以共享请垛,因此效率較高。

優(yōu)點(diǎn):開(kāi)銷較星⒁椤宗收!線程間部分?jǐn)?shù)據(jù)是共享的,且線程生成與線程間的切換所需資源開(kāi)銷比進(jìn)程間切換小得多亚兄。

缺點(diǎn):穩(wěn)定性混稽!線程切換過(guò)快可能造成線程抖動(dòng),且線程過(guò)多會(huì)造成服務(wù)器不穩(wěn)定审胚。

異步方式:使用非阻塞方式處理請(qǐng)求匈勋,是三種方式中開(kāi)銷最小的。但異步方式雖然效率高菲盾,但要求也高颓影,因?yàn)槎嗳蝿?wù)之間的調(diào)度如果出現(xiàn)問(wèn)題,就可能出現(xiàn)整體故障懒鉴,因此使用異步工作的诡挂,一般是一些功能相對(duì)簡(jiǎn)單碎浇,但卻符合服務(wù)器任務(wù)調(diào)度、且代碼中沒(méi)有影響調(diào)度的錯(cuò)誤代碼存在的程序璃俗。

優(yōu)點(diǎn):性能最好奴璃!一個(gè)進(jìn)程或線程處理多個(gè)請(qǐng)求,不需要額外開(kāi)銷城豁,性能最好苟穆,資源占用最低。

缺點(diǎn):穩(wěn)定性唱星!某個(gè)進(jìn)程或線程出錯(cuò)雳旅,可能導(dǎo)致大量請(qǐng)求無(wú)法處理,甚至導(dǎo)致整個(gè)服務(wù)宕機(jī)间聊。

2.2 一個(gè)Web請(qǐng)求的處理過(guò)程:

客戶發(fā)起情況到服務(wù)器網(wǎng)卡攒盈;

服務(wù)器網(wǎng)卡接受到請(qǐng)求后轉(zhuǎn)交給內(nèi)核處理;

內(nèi)核根據(jù)請(qǐng)求對(duì)應(yīng)的套接字哎榴,將請(qǐng)求交給工作在用戶空間的Web服務(wù)器進(jìn)程

Web服務(wù)器進(jìn)程根據(jù)用戶請(qǐng)求型豁,向內(nèi)核進(jìn)行系統(tǒng)調(diào)用,申請(qǐng)獲取相應(yīng)資源(如index.html)

內(nèi)核發(fā)現(xiàn)web服務(wù)器進(jìn)程請(qǐng)求的是一個(gè)存放在硬盤上的資源尚蝌,因此通過(guò)驅(qū)動(dòng)程序連接磁盤

內(nèi)核調(diào)度磁盤迎变,獲取需要的資源

內(nèi)核將資源存放在自己的緩沖區(qū)中,并通知Web服務(wù)器進(jìn)程

Web服務(wù)器進(jìn)程通過(guò)系統(tǒng)調(diào)用取得資源飘言,并將其復(fù)制到進(jìn)程自己的緩沖區(qū)中

Web服務(wù)器進(jìn)程形成響應(yīng)衣形,通過(guò)系統(tǒng)調(diào)用再次發(fā)給內(nèi)核以響應(yīng)用戶請(qǐng)求

內(nèi)核將響應(yīng)發(fā)送至網(wǎng)卡

網(wǎng)卡發(fā)送響應(yīng)給用戶

通過(guò)這樣的一個(gè)復(fù)雜過(guò)程,一次請(qǐng)求就完成了姿鸿。

簡(jiǎn)單來(lái)說(shuō)就是:用戶請(qǐng)求-->送達(dá)到用戶空間-->系統(tǒng)調(diào)用-->內(nèi)核空間-->內(nèi)核到磁盤上讀取網(wǎng)頁(yè)資源->返回到用戶空間->響應(yīng)給用戶泵喘。上述簡(jiǎn)單的說(shuō)明了一下,客戶端向Web服務(wù)請(qǐng)求過(guò)程般妙,在這個(gè)過(guò)程中纪铺,有兩個(gè)I/O過(guò)程,一個(gè)就是客戶端請(qǐng)求的網(wǎng)絡(luò)I/O碟渺,另一個(gè)就是Web服務(wù)器請(qǐng)求頁(yè)面的磁盤I/O鲜锚。 下面我們就來(lái)說(shuō)說(shuō)Linux的I/O模型。

三苫拍、各種I/O模型詳解

通過(guò)上面的對(duì)連接的處理分析芜繁,我們知道工作在用戶空間的web服務(wù)器進(jìn)程是無(wú)法直接操作IO的,需要通過(guò)系統(tǒng)調(diào)用進(jìn)行绒极,其關(guān)系如下:

即進(jìn)程向內(nèi)核進(jìn)行系統(tǒng)調(diào)用申請(qǐng)IO骏令,內(nèi)核將資源從IO調(diào)度到內(nèi)核的buffer中(wait階段),內(nèi)核還需將數(shù)據(jù)從內(nèi)核buffer中復(fù)制(copy階段)到web服務(wù)器進(jìn)程所在的用戶空間垄提,才算完成一次IO調(diào)度榔袋。這幾個(gè)階段都是需要時(shí)間的周拐。根據(jù)wait和copy階段的處理等待的機(jī)制不同,可將I/O動(dòng)作分為如下五種模式:

阻塞I/O

非阻塞I/O

I/O復(fù)用(select和poll)

信號(hào)(事件)驅(qū)動(dòng)I/O(SIGIO)

異步I/O(aio)

3.1 I/O模型簡(jiǎn)介

這里有必要先解釋一下阻塞凰兑、非阻塞妥粟,同步、異步吏够、I/O的概念勾给。

3.1.1 阻塞和非阻塞:

阻塞和非阻塞指的是執(zhí)行一個(gè)操作是等操作結(jié)束再返回,還是馬上返回锅知。

比如餐館的服務(wù)員為用戶點(diǎn)菜播急,當(dāng)有用戶點(diǎn)完菜后,服務(wù)員將菜單給后臺(tái)廚師售睹,此時(shí)有兩種方式:

第一種:就在出菜窗口等待旅择,直到廚師炒完菜后將菜送到窗口,然后服務(wù)員再將菜送到用戶手中侣姆;

第二種:等一會(huì)再到窗口來(lái)問(wèn)廚師,某個(gè)菜好了沒(méi)沉噩?如果沒(méi)有先處理其他事情捺宗,等會(huì)再去問(wèn)一次;

第一種就是阻塞方式川蒙,第二種則是非阻塞的蚜厉。

3.1.2 同步和異步:

同步和異步又是另外一個(gè)概念,它是事件本身的一個(gè)屬性畜眨。還拿前面點(diǎn)菜為例昼牛,服務(wù)員直接跟廚師打交道,菜出來(lái)沒(méi)出來(lái)康聂,服務(wù)員直接指導(dǎo)贰健,但只有當(dāng)廚師將菜送到服務(wù)員手上,這個(gè)過(guò)程才算正常完成恬汁,這就是同步的事件伶椿。同樣是點(diǎn)菜,有些餐館有專門的傳菜人員氓侧,當(dāng)廚師炒好菜后脊另,傳菜員將菜送到傳菜窗口,并通知服務(wù)員约巷,這就變成異步的了偎痛。其實(shí)異步還可以分為兩種:帶通知的和不帶通知的。前面說(shuō)的那種屬于帶通知的独郎。有些傳菜員干活可能主動(dòng)性不是很夠踩麦,不會(huì)主動(dòng)通知你枚赡,你就需要時(shí)不時(shí)的去關(guān)注一下?tīng)顟B(tài)。這種就是不帶通知的異步靖榕。

對(duì)于同步的事件标锄,你只能以阻塞的方式去做。而對(duì)于異步的事件茁计,阻塞和非阻塞都是可以的料皇。非阻塞又有兩種方式:主動(dòng)查詢和被動(dòng)接收消息。被動(dòng)不意味著一定不好星压,在這里它恰恰是效率更高的践剂,因?yàn)樵谥鲃?dòng)查詢里絕大部分的查詢是在做無(wú)用功。對(duì)于帶通知的異步事件娜膘,兩者皆可逊脯。而對(duì)于不帶通知的,則只能用主動(dòng)查詢竣贪。

3.1.3 全異步I/O

回到I/O军洼,不管是I還是O,對(duì)外設(shè)(磁盤)的訪問(wèn)都可以分成請(qǐng)求和執(zhí)行兩個(gè)階段演怎。請(qǐng)求就是看外設(shè)的狀態(tài)信息(比如是否準(zhǔn)備好了)匕争,執(zhí)行才是真正的I/O操作。在Linux 2.6之前爷耀,只有“請(qǐng)求”是異步事件甘桑,2.6之后才引入AIO(asynchronous I/O )把“執(zhí)行”異步化。別看Linux/Unix是用來(lái)做服務(wù)器的歹叮,這點(diǎn)上比Windows落后了好多跑杭,IOCP(Windows上的AIO,效率極高)在Win2000上就有了咆耿。所以學(xué)linux的別老覺(jué)得Windows這里不好那里不好(Windows的多線程機(jī)制也由于linux)德谅。

3.1.4 I/O的五種模型

根據(jù)以上分析,I/O可分為五種模型:

阻塞I/O:所有過(guò)程全阻塞

非阻塞I/O:如果沒(méi)有數(shù)據(jù)buffer萨螺,則立即返回EWOULDBLOCK

I/O復(fù)用(select和poll):在wait和copy階段分別阻塞

信號(hào)驅(qū)動(dòng)I/O(SIGIO):在wait階段不阻塞女阀,但copy階段阻塞(信號(hào)驅(qū)動(dòng)I/O,即通知)

異步I/O(aio):完全五阻塞方式屑迂,當(dāng)I/O完成是提供信號(hào)

Linux上的前四種I/O模型的“執(zhí)行”階段都是同步的浸策,只有最后一種才做到了真正的全異步。第一種阻塞式是最原始的方法惹盼,也是最累的辦法庸汗。當(dāng)然累與不累要看針對(duì)誰(shuí)。應(yīng)用程序是和內(nèi)核打交道的手报。對(duì)應(yīng)用程序來(lái)說(shuō)蚯舱,這種方式是最累的改化,但對(duì)內(nèi)核來(lái)說(shuō)這種方式恰恰是最省事的。還拿點(diǎn)菜這事為例枉昏,你就是應(yīng)用程序陈肛,廚師就是內(nèi)核,如果你去了一直等著兄裂,廚師就省事了(不用同時(shí)處理其他服務(wù)員的菜)句旱。當(dāng)然現(xiàn)在計(jì)算機(jī)的設(shè)計(jì),包括操作系統(tǒng)晰奖,越來(lái)越為終端用戶考慮了谈撒,為了讓用戶滿意,內(nèi)核慢慢的承擔(dān)起越來(lái)越多的工作匾南,IO模型的演化也是如此啃匿。

非阻塞I/O ,I/O復(fù)用蛆楞,信號(hào)驅(qū)動(dòng)式I/O其實(shí)都是非阻塞的溯乒,當(dāng)然是針對(duì)“請(qǐng)求”這個(gè)階段。非阻塞式是主動(dòng)查詢外設(shè)狀態(tài)豹爹。I/O復(fù)用里的select裆悄,poll也是主動(dòng)查詢,不同的是select和poll可以同時(shí)查詢多個(gè)fd(文件句柄)的狀態(tài)帅戒,另外select有fd個(gè)數(shù)的限制。epoll是基于回調(diào)函數(shù)的崖技。信號(hào)驅(qū)動(dòng)式I/O則是基于信號(hào)消息的逻住。這兩個(gè)應(yīng)該可以歸到“被動(dòng)接收消息”那一類中。最后就是偉大的AIO的出現(xiàn)迎献,內(nèi)核把什么事都干了瞎访,對(duì)上層應(yīng)用實(shí)現(xiàn)了全異步,性能最好吁恍,當(dāng)然復(fù)雜度也最高扒秸。

3.2 各I/O模型詳細(xì)介紹:

3.2.1 阻塞I/O

說(shuō)明:應(yīng)用程序調(diào)用一個(gè)IO函數(shù),導(dǎo)致應(yīng)用程序阻塞冀瓦,等待數(shù)據(jù)準(zhǔn)備好伴奥。 如果數(shù)據(jù)沒(méi)有準(zhǔn)備好,一直等待數(shù)據(jù)準(zhǔn)備好了翼闽,從內(nèi)核拷貝到用戶空間,IO函數(shù)返回成功指示拾徙。這個(gè)不用多解釋吧,阻塞套接字感局。下圖是它調(diào)用過(guò)程的圖示:(注尼啡,一般網(wǎng)絡(luò)I/O都是阻塞I/O暂衡,客戶端發(fā)出請(qǐng)求锌雀,Web服務(wù)器進(jìn)程響應(yīng)匿级,在進(jìn)程沒(méi)有返回頁(yè)面之前秩冈,這個(gè)請(qǐng)求會(huì)處于一直等待狀態(tài))


3.2.2 非阻塞I/O

我們把一個(gè)套接口設(shè)置為非阻塞就是告訴內(nèi)核鳖粟,當(dāng)所請(qǐng)求的I/O操作無(wú)法完成時(shí)上遥,不要將進(jìn)程睡眠煞檩,而是返回一個(gè)錯(cuò)誤焰手。這樣我們的I/O操作函數(shù)將不斷的測(cè)試數(shù)據(jù)是否已經(jīng)準(zhǔn)備好述呐,如果沒(méi)有準(zhǔn)備好寺惫,繼續(xù)測(cè)試疹吃,直到數(shù)據(jù)準(zhǔn)備好為止。在這個(gè)不斷測(cè)試的過(guò)程中西雀,會(huì)大量的占用CPU的時(shí)間萨驶,所有一般Web服務(wù)器都不使用這種I/O模型。具體過(guò)程如下圖:


3.2.3 I/O復(fù)用(select和poll)

I/O復(fù)用模型會(huì)用到select或poll函數(shù)或epoll函數(shù)(Linux2.6以后的內(nèi)核開(kāi)始支持)艇肴,這兩個(gè)函數(shù)也會(huì)使進(jìn)程阻塞腔呜,但是和阻塞I/O所不同的的,這兩個(gè)函數(shù)可以同時(shí)阻塞多個(gè)I/O操作再悼。而且可以同時(shí)對(duì)多個(gè)讀操作核畴,多個(gè)寫操作的I/O函數(shù)進(jìn)行檢測(cè),直到有數(shù)據(jù)可讀或可寫時(shí)冲九,才真正調(diào)用I/O操作函數(shù)谤草。具體過(guò)程如下圖:


3.2.4 信號(hào)驅(qū)動(dòng)I/O(SIGIO)

首先,我們?cè)试S套接口進(jìn)行信號(hào)驅(qū)動(dòng)I/O莺奸,并安裝一個(gè)信號(hào)處理函數(shù)丑孩,進(jìn)程繼續(xù)運(yùn)行并不阻塞。當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí)灭贷,進(jìn)程會(huì)收到一個(gè)SIGIO信號(hào)温学,可以在信號(hào)處理函數(shù)中調(diào)用I/O操作函數(shù)處理數(shù)據(jù)。具體過(guò)程如下圖:

3.2.5 異步I/O(aio)

當(dāng)一個(gè)異步過(guò)程調(diào)用發(fā)出后甚疟,調(diào)用者不能立刻得到結(jié)果仗岖。實(shí)際處理這個(gè)調(diào)用的部件在完成后,通過(guò)狀態(tài)览妖、通知和回調(diào)來(lái)通知調(diào)用者的輸入輸出操作轧拄。具體過(guò)程如下圖:

3.2.6 I/O 模型總結(jié)(如下圖)


從上圖中我們可以看出,可以看出讽膏,越往后紧帕,阻塞越少,理論上效率也是最優(yōu)。其五種I/O模型中是嗜,前三種屬于同步I/O愈案,后兩者屬于異步I/O。

同步I/O:

阻塞I/O

非阻塞I/O

I/O復(fù)用(select和poll)

異步I/O:

信號(hào)驅(qū)動(dòng)I/O(SIGIO) (半異步)

異步I/O(aio) (真正的異步)

異步 I/O 和 信號(hào)驅(qū)動(dòng)I/O的區(qū)別:

信號(hào)驅(qū)動(dòng) I/O 模式下鹅搪,內(nèi)核可以復(fù)制的時(shí)候通知給我們的應(yīng)用程序發(fā)送SIGIO 消息站绪。

異步 I/O 模式下,內(nèi)核在所有的操作都已經(jīng)被內(nèi)核操作結(jié)束之后才會(huì)通知我們的應(yīng)用程序丽柿。

3.3 Linux I/O模型的具體實(shí)現(xiàn)

3.3.1 主要實(shí)現(xiàn)方式有以下幾種:

select

poll

epoll

kqueue

/dev/poll

iocp

注恢准,其中iocp是Windows實(shí)現(xiàn)的,select甫题、poll馁筐、epoll是Linux實(shí)現(xiàn)的,kqueue是FreeBSD實(shí)現(xiàn)的坠非,/dev/poll是SUN的Solaris實(shí)現(xiàn)的敏沉。select、poll對(duì)應(yīng)第3種(I/O復(fù)用)模型炎码,iocp對(duì)應(yīng)第5種(異步I/O)模型盟迟,那么epoll、kqueue潦闲、/dev/poll呢攒菠?其實(shí)也同select屬于同一種模型,只是更高級(jí)一些歉闰,可以看作有了第4種(信號(hào)驅(qū)動(dòng)I/O)模型的某些特性辖众,如callback機(jī)制。

3.3.2 為什么epoll和敬、kqueue凹炸、/dev/poll比select高級(jí)?

答案是概龄,他們無(wú)輪詢还惠。因?yàn)樗麄冇胏allback取代了饲握。想想看私杜,當(dāng)套接字比較多的時(shí)候,每次select()都要通過(guò)遍歷FD_SETSIZE個(gè)Socket來(lái)完成調(diào)度救欧,不管哪個(gè)Socket是活躍的衰粹,都遍歷一遍。這會(huì)浪費(fèi)很多CPU時(shí)間笆怠。如果能給套接字注冊(cè)某個(gè)回調(diào)函數(shù)铝耻,當(dāng)他們活躍時(shí),自動(dòng)完成相關(guān)操作,那就避免了輪詢瓢捉,這正是epoll频丘、kqueue、/dev/poll做的泡态。這樣子說(shuō)可能不好理解搂漠,那么我說(shuō)一個(gè)現(xiàn)實(shí)中的例子,假設(shè)你在大學(xué)讀書(shū)某弦,住的宿舍樓有很多間房間桐汤,你的朋友要來(lái)找你。select版宿管大媽就會(huì)帶著你的朋友挨個(gè)房間去找靶壮,直到找到你為止怔毛。而epoll版宿管大媽會(huì)先記下每位同學(xué)的房間號(hào),你的朋友來(lái)時(shí)腾降,只需告訴你的朋友你住在哪個(gè)房間即可拣度,不用親自帶著你的朋友滿大樓找人。如果來(lái)了10000個(gè)人蜂莉,都要找自己住這棟樓的同學(xué)時(shí)蜡娶,select版和epoll版宿管大媽,誰(shuí)的效率更高映穗,不言自明窖张。同理,在高并發(fā)服務(wù)器中蚁滋,輪詢I/O是最耗時(shí)間的操作之一宿接,select、epoll辕录、/dev/poll的性能誰(shuí)的性能更高睦霎,同樣十分明了。

3.3.3 Windows or *nix (IOCP or kqueue走诞、epoll副女、/dev/poll)?

誠(chéng)然蚣旱,Windows的IOCP非常出色碑幅,目前很少有支持asynchronous I/O的系統(tǒng),但是由于其系統(tǒng)本身的局限性塞绿,大型服務(wù)器還是在UNIX下沟涨。而且正如上面所述,kqueue异吻、epoll裹赴、/dev/poll 與 IOCP相比,就是多了一層從內(nèi)核copy數(shù)據(jù)到應(yīng)用層的阻塞,從而不能算作asynchronous I/O類棋返。但是延都,這層小小的阻塞無(wú)足輕重,kqueue睛竣、epoll窄潭、/dev/poll 已經(jīng)做得很優(yōu)秀了。

3.3.4 總結(jié)一些重點(diǎn)

只有IOCP(windows實(shí)現(xiàn))是asynchronous I/O酵颁,其他機(jī)制或多或少都會(huì)有一點(diǎn)阻塞嫉你。

select(Linux實(shí)現(xiàn))低效是因?yàn)槊看嗡夹枰喸儭5托б彩窍鄬?duì)的躏惋,視情況而定幽污,也可通過(guò)良好的設(shè)計(jì)改善

epoll(Linux實(shí)現(xiàn))、kqueue(FreeBSD實(shí)現(xiàn))簿姨、/dev/poll(Solaris實(shí)現(xiàn))是Reacor模式距误,IOCP是Proactor模式。

Apache 2.2.9之前只支持select模型扁位,2.2.9之后支持epoll模型

Nginx 支持epoll模型

Java nio包是select模型

四准潭、Apache Httpd的工作模式

4.1 apache三種工作模式

我們都知道Apache有三種工作模塊,分別為prefork域仇、worker刑然、event。

prefork:多進(jìn)程暇务,每個(gè)請(qǐng)求用一個(gè)進(jìn)程響應(yīng)泼掠,這個(gè)過(guò)程會(huì)用到select機(jī)制來(lái)通知。

worker:多線程垦细,一個(gè)進(jìn)程可以生成多個(gè)線程择镇,每個(gè)線程響應(yīng)一個(gè)請(qǐng)求,但通知機(jī)制還是select不過(guò)可以接受更多的請(qǐng)求括改。

event:基于異步I/O模型腻豌,一個(gè)進(jìn)程或線程,每個(gè)進(jìn)程或線程響應(yīng)多個(gè)用戶請(qǐng)求嘱能,它是基于事件驅(qū)動(dòng)(也就是epoll機(jī)制)實(shí)現(xiàn)的吝梅。

4.2 prefork的工作原理

如果不用“--with-mpm”顯式指定某種MPM,prefork就是Unix平臺(tái)上缺省的MPM.它所采用的預(yù)派生子進(jìn)程方式也是 Apache1.3中采用的模式。prefork本身并沒(méi)有使用到線程焰檩,2.0版使用它是為了與1.3版保持兼容性憔涉;另一方面订框,prefork用單獨(dú)的子進(jìn)程來(lái)處理不同的請(qǐng)求析苫,進(jìn)程之間是彼此獨(dú)立的,這也使其成為最穩(wěn)定的MPM之一。

4.3 worker的工作原理

相對(duì)于prefork,worker是2.0版中全新的支持多線程和多進(jìn)程混合模型的MPM衩侥。由于使用線程來(lái)處理国旷,所以可以處理相對(duì)海量的請(qǐng)求,而系統(tǒng)資源的開(kāi)銷要小于基于進(jìn)程的服務(wù)器茫死。但是跪但,worker也使用了多進(jìn)程,每個(gè)進(jìn)程又生成多個(gè)線程,以獲得基于進(jìn)程服務(wù)器的穩(wěn)定性峦萎,這種MPM的工作方 式將是Apache2.0的發(fā)展趨勢(shì)屡久。

4.4 event 基于事件機(jī)制的特性

一個(gè)進(jìn)程響應(yīng)多個(gè)用戶請(qǐng)求,利用callback機(jī)制爱榔,讓套接字復(fù)用被环,請(qǐng)求過(guò)來(lái)后進(jìn)程并不處理請(qǐng)求,而是直接交由其他機(jī)制來(lái)處理详幽,通過(guò)epoll機(jī)制來(lái)通知請(qǐng)求是否完成筛欢;在這個(gè)過(guò)程中,進(jìn)程本身一直處于空閑狀態(tài)唇聘,可以一直接收用戶請(qǐng)求版姑。可以實(shí)現(xiàn)一個(gè)進(jìn)程程響應(yīng)多個(gè)用戶請(qǐng)求迟郎。支持持海量并發(fā)連接數(shù)剥险,消耗更少的資源。

五宪肖、如何提高Web服務(wù)器的并發(fā)連接處理能力

有幾個(gè)基本條件:

基于線程炒嘲,即一個(gè)進(jìn)程生成多個(gè)線程,每個(gè)線程響應(yīng)用戶的每個(gè)請(qǐng)求匈庭。

基于事件的模型夫凸,一個(gè)進(jìn)程處理多個(gè)請(qǐng)求,并且通過(guò)epoll機(jī)制來(lái)通知用戶請(qǐng)求完成阱持。

基于磁盤的AIO(異步I/O)

支持mmap內(nèi)存映射夭拌,mmap傳統(tǒng)的web服務(wù)器,進(jìn)行頁(yè)面輸入時(shí)衷咽,都是將磁盤的頁(yè)面先輸入到內(nèi)核緩存中鸽扁,再由內(nèi)核緩存中復(fù)制一份到web服務(wù)器上,mmap機(jī)制就是讓內(nèi)核緩存與磁盤進(jìn)行映射镶骗,web服務(wù)器桶现,直接復(fù)制頁(yè)面內(nèi)容即可。不需要先把磁盤的上的頁(yè)面先輸入到內(nèi)核緩存去鼎姊。

剛好骡和,Nginx 支持以上所有特性相赁。所以Nginx官網(wǎng)上說(shuō),Nginx支持50000并發(fā)慰于,是有依據(jù)的钮科。

六、Nginx優(yōu)異之處

6.1 簡(jiǎn)介

傳統(tǒng)上基于進(jìn)程或線程模型架構(gòu)的web服務(wù)通過(guò)每進(jìn)程或每線程處理并發(fā)連接請(qǐng)求婆赠,這勢(shì)必會(huì)在網(wǎng)絡(luò)和I/O操作時(shí)產(chǎn)生阻塞绵脯,其另一個(gè)必然結(jié)果則是對(duì)內(nèi)存或CPU的利用率低下。生成一個(gè)新的進(jìn)程/線程需要事先備好其運(yùn)行時(shí)環(huán)境休里,這包括為其分配堆內(nèi)存和棧內(nèi)存蛆挫,以及為其創(chuàng)建新的執(zhí)行上下文等。這些操作都需要占用CPU妙黍,而且過(guò)多的進(jìn)程/線程還會(huì)帶來(lái)線程抖動(dòng)或頻繁的上下文切換璃吧,系統(tǒng)性能也會(huì)由此進(jìn)一步下降。另一種高性能web服務(wù)器/web服務(wù)器反向代理:Nginx(Engine X)废境,nginx的主要著眼點(diǎn)就是其高性能以及對(duì)物理計(jì)算資源的高密度利用畜挨,因此其采用了不同的架構(gòu)模型。受啟發(fā)于多種操作系統(tǒng)設(shè)計(jì)中基于“事件”的高級(jí)處理機(jī)制噩凹,nginx采用了模塊化巴元、事件驅(qū)動(dòng)、異步驮宴、單線程及非阻塞的架構(gòu)逮刨,并大量采用了多路復(fù)用及事件通知機(jī)制。在nginx中堵泽,連接請(qǐng)求由為數(shù)不多的幾個(gè)僅包含一個(gè)線程的進(jìn)程worker以高效的回環(huán)(run-loop)機(jī)制進(jìn)行處理修己,而每個(gè)worker可以并行處理數(shù)千個(gè)的并發(fā)連接及請(qǐng)求。

6.2 Nginx 工作原理

Nginx會(huì)按需同時(shí)運(yùn)行多個(gè)進(jìn)程:一個(gè)主進(jìn)程(master)和幾個(gè)工作進(jìn)程(worker)迎罗,配置了緩存時(shí)還會(huì)有緩存加載器進(jìn)程(cache loader)和緩存管理器進(jìn)程(cache manager)等睬愤。所有進(jìn)程均是僅含有一個(gè)線程,并主要通過(guò)“共享內(nèi)存”的機(jī)制實(shí)現(xiàn)進(jìn)程間通信纹安。主進(jìn)程以root用戶身份運(yùn)行尤辱,而worker、cache loader和cache manager均應(yīng)以非特權(quán)用戶身份運(yùn)行厢岂。

主進(jìn)程主要完成如下工作:

讀取并驗(yàn)正配置信息光督;

創(chuàng)建、綁定及關(guān)閉套接字塔粒;

啟動(dòng)结借、終止及維護(hù)worker進(jìn)程的個(gè)數(shù);

無(wú)須中止服務(wù)而重新配置工作特性卒茬;

控制非中斷式程序升級(jí)船老,啟用新的二進(jìn)制程序并在需要時(shí)回滾至老版本咖熟;

重新打開(kāi)日志文件;

編譯嵌入式perl腳本努隙;

worker進(jìn)程主要完成的任務(wù)包括:

接收、傳入并處理來(lái)自客戶端的連接辜昵;

提供反向代理及過(guò)濾功能荸镊;

nginx任何能完成的其它任務(wù);

注:如果負(fù)載以CPU密集型應(yīng)用為主堪置,如SSL或壓縮應(yīng)用躬存,則worker數(shù)應(yīng)與CPU數(shù)相同;如果負(fù)載以IO密集型為主舀锨,如響應(yīng)大量?jī)?nèi)容給客戶端岭洲,則worker數(shù)應(yīng)該為CPU個(gè)數(shù)的1.5或2倍。

6.3 Nginx 架構(gòu)

Nginx的代碼是由一個(gè)核心和一系列的模塊組成, 核心主要用于提供Web Server的基本功能坎匿,以及Web和Mail反向代理的功能盾剩;還用于啟用網(wǎng)絡(luò)協(xié)議,創(chuàng)建必要的運(yùn)行時(shí)環(huán)境以及確保不同的模塊之間平滑地進(jìn)行交互替蔬。不過(guò)告私,大多跟協(xié)議相關(guān)的功能和某應(yīng)用特有的功能都是由nginx的模塊實(shí)現(xiàn)的。這些功能模塊大致可以分為事件模塊承桥、階段性處理器驻粟、輸出過(guò)濾器、變量處理器凶异、協(xié)議蜀撑、upstream和負(fù)載均衡幾個(gè)類別,這些共同組成了nginx的http功能剩彬。事件模塊主要用于提供OS獨(dú)立的(不同操作系統(tǒng)的事件機(jī)制有所不同)事件通知機(jī)制如kqueue或epoll等酷麦。協(xié)議模塊則負(fù)責(zé)實(shí)現(xiàn)nginx通過(guò)http、tls/ssl喉恋、smtp贴铜、pop3以及imap與對(duì)應(yīng)的客戶端建立會(huì)話。在Nginx內(nèi)部瀑晒,進(jìn)程間的通信是通過(guò)模塊的pipeline或chain實(shí)現(xiàn)的绍坝;換句話說(shuō),每一個(gè)功能或操作都由一個(gè)模塊來(lái)實(shí)現(xiàn)苔悦。例如轩褐,壓縮、通過(guò)FastCGI或uwsgi協(xié)議與upstream服務(wù)器通信玖详,以及與memcached建立會(huì)話等把介。

6.4 Nginx 基礎(chǔ)功能

處理靜態(tài)文件勤讽,索引文件以及自動(dòng)索引;

反向代理加速(無(wú)緩存)拗踢,簡(jiǎn)單的負(fù)載均衡和容錯(cuò)脚牍;

FastCGI,簡(jiǎn)單的負(fù)載均衡和容錯(cuò)巢墅;

模塊化的結(jié)構(gòu)诸狭。過(guò)濾器包括gzipping, byte ranges, chunked responses, 以及 SSI-filter 。在SSI過(guò)濾器中君纫,到同一個(gè) proxy 或者 FastCGI 的多個(gè)子請(qǐng)求并發(fā)處理驯遇;

SSL 和 TLS SNI 支持;

6.5 Nginx IMAP/POP3 代理服務(wù)功能

使用外部 HTTP 認(rèn)證服務(wù)器重定向用戶到 IMAP/POP3 后端蓄髓;

使用外部 HTTP 認(rèn)證服務(wù)器認(rèn)證用戶后連接重定向到內(nèi)部的 SMTP 后端叉庐;

認(rèn)證方法:

POP3: POP3 USER/PASS, APOP, AUTH LOGIN PLAIN CRAM-MD5;

IMAP: IMAP LOGIN;

SMTP: AUTH LOGIN PLAIN CRAM-MD5;

SSL 支持;

在 IMAP 和 POP3 模式下的 STARTTLS 和 STLS 支持会喝;

6.6 Nginx 支持的操作系統(tǒng)

FreeBSD 3.x, 4.x, 5.x, 6.x i386; FreeBSD 5.x, 6.x amd64;

Linux 2.2, 2.4, 2.6 i386; Linux 2.6 amd64;

Solaris 8 i386; Solaris 9 i386 and sun4u; Solaris 10 i386;

MacOS X (10.4) PPC;

Windows 編譯版本支持 windows 系列操作系統(tǒng);

6.7 Nginx 結(jié)構(gòu)與擴(kuò)展

一個(gè)主進(jìn)程和多個(gè)工作進(jìn)程陡叠,工作進(jìn)程運(yùn)行于非特權(quán)用戶;

kqueue (FreeBSD 4.1+), epoll (Linux 2.6+), rt signals (Linux 2.2.19+), /dev/poll (Solaris 7 11/99+), select, 以及 poll 支持肢执;

kqueue支持的不同功能包括 EV_CLEAR, EV_DISABLE (臨時(shí)禁止事件)匾竿, NOTE_LOWAT, EV_EOF, 有效數(shù)據(jù)的數(shù)目,錯(cuò)誤代碼蔚万;

sendfile (FreeBSD 3.1+), sendfile (Linux 2.2+), sendfile64 (Linux 2.4.21+), 和 sendfilev (Solaris 8 7/01+) 支持岭妖;

輸入過(guò)濾 (FreeBSD 4.1+) 以及 TCP_DEFER_ACCEPT (Linux 2.4+) 支持;

10,000 非活動(dòng)的 HTTP keep-alive 連接僅需要 2.5M 內(nèi)存反璃。

最小化的數(shù)據(jù)拷貝操作昵慌;

6.8 Nginx 其他HTTP功能

基于IP 和名稱的虛擬主機(jī)服務(wù);

Memcached 的 GET 接口淮蜈;

支持 keep-alive 和管道連接斋攀;

靈活簡(jiǎn)單的配置;

重新配置和在線升級(jí)而無(wú)須中斷客戶的工作進(jìn)程梧田;

可定制的訪問(wèn)日志淳蔼,日志寫入緩存,以及快捷的日志回卷裁眯;

4xx-5xx 錯(cuò)誤代碼重定向鹉梨;

基于 PCRE 的 rewrite 重寫模塊;

基于客戶端 IP 地址和 HTTP 基本認(rèn)證的訪問(wèn)控制穿稳;

PUT, DELETE, 和 MKCOL 方法存皂;

支持 FLV (Flash 視頻);

帶寬限制逢艘;

6.9 為什么選擇Nginx

在高連接并發(fā)的情況下旦袋,Nginx是Apache服務(wù)器不錯(cuò)的替代品: Nginx在美國(guó)是做虛擬主機(jī)生意的老板們經(jīng)常選擇的軟件平臺(tái)之一. 能夠支持高達(dá) 50,000 個(gè)并發(fā)連接數(shù)的響應(yīng), 感謝Nginx為我們選擇了 epoll and kqueue 作為開(kāi)發(fā)模型骤菠。

Nginx作為負(fù)載均衡服務(wù)器: Nginx 既可以在內(nèi)部直接支持 Rails 和 PHP 程序?qū)ν膺M(jìn)行服務(wù), 也可以支持作為 HTTP代理 服務(wù)器對(duì)外進(jìn)行服務(wù). Nginx采用C進(jìn)行編寫, 不論是系統(tǒng)資源開(kāi)銷還是CPU使用效率都比 Perlbal 要好很多。

作為郵件代理服務(wù)器: Nginx 同時(shí)也是一個(gè)非常優(yōu)秀的郵件代理服務(wù)器(最早開(kāi)發(fā)這個(gè)產(chǎn)品的目的之一也是作為郵件代理服務(wù)器), Last.fm 描述了成功并且美妙的使用經(jīng)驗(yàn).

Nginx 安裝非常的簡(jiǎn)單 , 配置文件非常簡(jiǎn)潔(還能夠支持perl語(yǔ)法),Bugs 非常少的服務(wù)器: Nginx 啟動(dòng)特別容易, 并且?guī)缀蹩梢宰龅?*24不間斷運(yùn)行疤孕,即使運(yùn)行數(shù)個(gè)月也不需要重新啟動(dòng). 你還能夠 不間斷服務(wù)的情況下進(jìn)行軟件版本的升級(jí) 商乎。

Nginx 的誕生主要解決C10K問(wèn)題

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市祭阀,隨后出現(xiàn)的幾起案子鹉戚,更是在濱河造成了極大的恐慌,老刑警劉巖柬讨,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崩瓤,死亡現(xiàn)場(chǎng)離奇詭異袍啡,居然都是意外死亡踩官,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門境输,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蔗牡,“玉大人,你說(shuō)我怎么就攤上這事嗅剖”缭剑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵信粮,是天一觀的道長(zhǎng)黔攒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)强缘,這世上最難降的妖魔是什么督惰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮旅掂,結(jié)果婚禮上赏胚,老公的妹妹穿的比我還像新娘。我一直安慰自己商虐,他們只是感情好觉阅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著秘车,像睡著了一般典勇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叮趴,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天痴柔,我揣著相機(jī)與錄音,去河邊找鬼疫向。 笑死咳蔚,一個(gè)胖子當(dāng)著我的面吹牛豪嚎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谈火,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼侈询,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了糯耍?” 一聲冷哼從身側(cè)響起扔字,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎温技,沒(méi)想到半個(gè)月后革为,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舵鳞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年震檩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜓堕。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抛虏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出套才,到底是詐尸還是另有隱情迂猴,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布背伴,位于F島的核電站沸毁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏傻寂。R本人自食惡果不足惜息尺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望崎逃。 院中可真熱鬧掷倔,春花似錦、人聲如沸个绍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)巴柿。三九已至凛虽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間广恢,已是汗流浹背凯旋。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人至非。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓钠署,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親荒椭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谐鼎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容