傳統(tǒng)服務(wù)器模型
傳統(tǒng)的服務(wù)器模型如Apache 為每一個(gè)請(qǐng)求生成一個(gè)子進(jìn)程越锈。當(dāng)用戶連接到服務(wù)器時(shí) 一個(gè)子進(jìn)程就產(chǎn)生,并做連接處理仅淑。每個(gè)連接獲得一個(gè)單獨(dú)的線程和子進(jìn)程晕拆。當(dāng)用戶請(qǐng)求數(shù)據(jù)返回時(shí)萝风,子進(jìn)程開(kāi)始等待數(shù)據(jù)庫(kù)操作返回嘀掸。此時(shí)另外一個(gè)用戶也發(fā)起請(qǐng)求的時(shí)候。這時(shí)候就產(chǎn)品了阻塞规惰。
這種模式在小的工作負(fù)荷時(shí)表現(xiàn)良好睬塌,當(dāng)請(qǐng)求的數(shù)量變得很大時(shí)候服務(wù)器的壓力會(huì)過(guò)于巨大。比如達(dá)到Apache最大進(jìn)程數(shù)時(shí)候歇万,所有的進(jìn)程會(huì)變得很緩慢衫仑。
fork操作延時(shí)
新建進(jìn)程的性能很大依賴于操作系統(tǒng)的對(duì)fork的實(shí)現(xiàn),不同的操作系統(tǒng)處理并非都很理想堕花,都會(huì)有不同的延時(shí)文狱。
進(jìn)程調(diào)度
Linux每10ms中斷一次在運(yùn)行態(tài)的進(jìn)程,查看是否需要切換別的進(jìn)程執(zhí)行缘挽。進(jìn)程調(diào)度的任務(wù)就是決定下一個(gè)應(yīng)該執(zhí)行的進(jìn)程瞄崇,難度就在于如何公平的分配CPU資源
內(nèi)存占用和線程
創(chuàng)建多個(gè)進(jìn)程會(huì)帶來(lái)另外一個(gè)問(wèn)題:內(nèi)存消耗,每一個(gè)創(chuàng)建的進(jìn)程都會(huì)占用內(nèi)存。
可靠性
該模型具有可靠性的問(wèn)題壕曼,一個(gè)配置不當(dāng)?shù)姆?wù)器苏研,很容易受到拒絕服務(wù)攻擊(Dos)。當(dāng)大量并發(fā)請(qǐng)求的服務(wù)資源時(shí)腮郊,負(fù)載均衡配置不當(dāng)時(shí)摹蘑,服務(wù)器很快會(huì)耗盡資源而崩潰
同步阻塞IO
應(yīng)用程序執(zhí)行一個(gè)系統(tǒng)調(diào)用,這會(huì)導(dǎo)致應(yīng)用程序阻塞轧飞。這意味著應(yīng)用程序會(huì)一直阻塞衅鹿,直到系統(tǒng)調(diào)用完成為止(數(shù)據(jù)傳輸完成或發(fā)生錯(cuò)誤)。調(diào)用應(yīng)用程序處于一種不再占用CPU过咬,而只是簡(jiǎn)單等待響應(yīng)的狀態(tài)大渤,但是該進(jìn)程依然占用著資源。當(dāng)大量并發(fā)I/O請(qǐng)求到達(dá)時(shí)掸绞,則會(huì)產(chǎn)生I/O阻塞泵三,造成服務(wù)器瓶頸。
事件驅(qū)動(dòng)模型
操作系統(tǒng)并不是設(shè)計(jì)來(lái)處理服務(wù)器工作的負(fù)載。操作系統(tǒng)的設(shè)計(jì)是讓用戶執(zhí)行的多線程程序烫幕,使后臺(tái)文件寫入和UI操作同時(shí)進(jìn)程俺抽,而并不是設(shè)計(jì)處理大量并發(fā)請(qǐng)求的連接
Fork和多線程是相當(dāng)耗費(fèi)資源的操作,創(chuàng)建線程需要分配一個(gè)權(quán)限的內(nèi)存堆棧较曼。此外凌埂,上下文的切換也是一項(xiàng)開(kāi)銷,CPU調(diào)度模型并不適合一個(gè)傳統(tǒng)的Web服務(wù)器诗芜。因此傳統(tǒng)的服務(wù)器模型面臨多進(jìn)程多線程延遲以及內(nèi)存消耗的問(wèn)題瞳抓。要解決C10K(就是單機(jī)1萬(wàn)個(gè)并發(fā)連接問(wèn)題)問(wèn)題顯得十分復(fù)雜。
由于網(wǎng)絡(luò)負(fù)載工作包含大量的等待伏恐,比如Apache服務(wù)器:產(chǎn)生大量的子進(jìn)程孩哑,需要消耗大量的內(nèi)存。但是大多數(shù)的子進(jìn)程占用大量?jī)?nèi)存資源卻只是等待一個(gè)阻塞任務(wù)的結(jié)束翠桦。所以新的模型拋棄了對(duì)每個(gè)請(qǐng)求生成子進(jìn)程的想法横蜒。所有的請(qǐng)求和事物操作只使用一個(gè)單獨(dú)的線程管理,此線程稱為事件循環(huán)
销凑。事件循環(huán)將一部的管理所有用戶連接和文件讀取或者數(shù)據(jù)庫(kù)服務(wù)器丛晌。當(dāng)請(qǐng)求到達(dá)時(shí),使用poll或者select喚醒操作系統(tǒng)對(duì)其請(qǐng)求做相應(yīng)處理斗幼。這樣一來(lái)處理的并發(fā)請(qǐng)求不再是緊緊圍繞在阻塞資源澎蛛。
當(dāng)然,這樣也有一定的開(kāi)銷蜕窿,如保持一個(gè)始終打開(kāi)的TCP連接的列表谋逻,但內(nèi)存并不會(huì)由于大量并發(fā)請(qǐng)求而急速上升,因?yàn)檫@個(gè)列表只占內(nèi)存堆上很小的一部分桐经。