一、反向代理:Web服務(wù)器的“經(jīng)紀(jì)人”
1.1 反向代理初印象
反向代理(Reverse Proxy)方式是指以代理服務(wù)器來(lái)接受internet上的連接請(qǐng)求,然后將請(qǐng)求轉(zhuǎn)發(fā)給內(nèi)部網(wǎng)絡(luò)上的服務(wù)器,并將從服務(wù)器上得到的結(jié)果返回給internet上請(qǐng)求連接的客戶端,此時(shí)代理服務(wù)器對(duì)外就表現(xiàn)為一個(gè)服務(wù)器。
從上圖可以看出:反向代理服務(wù)器位于網(wǎng)站機(jī)房,代理網(wǎng)站W(wǎng)eb服務(wù)器接收Http請(qǐng)求,對(duì)請(qǐng)求進(jìn)行轉(zhuǎn)發(fā)。
1.2 反向代理的作用
①保護(hù)網(wǎng)站安全:任何來(lái)自Internet的請(qǐng)求都必須先經(jīng)過(guò)代理服務(wù)器;
②通過(guò)配置緩存功能加速Web請(qǐng)求:可以緩存真實(shí)Web服務(wù)器上的某些靜態(tài)資源,減輕真實(shí)Web服務(wù)器的負(fù)載壓力;
③實(shí)現(xiàn)負(fù)載均衡:充當(dāng)負(fù)載均衡服務(wù)器均衡地分發(fā)請(qǐng)求,平衡集群中各個(gè)服務(wù)器的負(fù)載壓力;
二、初識(shí)Nginx:簡(jiǎn)單卻不平凡
2.1 Nginx是神馬?
Nginx是一款輕量級(jí)的網(wǎng)頁(yè)服務(wù)器、反向代理器以及電子郵件代理服務(wù)器。其將源代碼以類(lèi)BSD許可證的形式發(fā)布,因它的穩(wěn)定性、豐富的功能集、示例配置文件和低系統(tǒng)資源的消耗而聞名。
Source:Nginx(發(fā)音同engine x),它是由俄羅斯程序員Igor Sysoev所開(kāi)發(fā)的。起初是供俄國(guó)大型的門(mén)戶網(wǎng)站及搜索引擎Rambler(俄語(yǔ):Рамблер)使用。此軟件BSD-like協(xié)議下發(fā)行,可以在UNIX、GNU/Linux、BSD、Mac OS X、Solaris,以及Microsoft Windows等操作系統(tǒng)中運(yùn)行。
說(shuō)到Web服務(wù)器,Apache服務(wù)器和IIS服務(wù)器是兩大巨頭;但是運(yùn)行速度更快、更靈活的對(duì)手:Nginx 正在迎頭趕上。
2.2 Nginx的應(yīng)用現(xiàn)狀
Nginx 已經(jīng)在俄羅斯最大的門(mén)戶網(wǎng)站── Rambler Media(www.rambler.ru)上運(yùn)行了3年時(shí)間,同時(shí)俄羅斯超過(guò)20%的虛擬主機(jī)平臺(tái)采用Nginx作為反向代理服務(wù)器。
在國(guó)內(nèi),已經(jīng)有 淘寶、新浪博客、新浪播客、網(wǎng)易新聞、六間房、56.com、Discuz!、水木社區(qū)、豆瓣、YUPOO、海內(nèi)、迅雷在線 等多家網(wǎng)站使用 Nginx 作為Web服務(wù)器或反向代理服務(wù)器。
2.3 Nginx的核心特點(diǎn)
(1)跨平臺(tái):Nginx 可以在大多數(shù) Unix like OS編譯運(yùn)行,而且也有Windows的移植版本;
(2)配置異常簡(jiǎn)單:非常容易上手。配置風(fēng)格跟程序開(kāi)發(fā)一樣,神一般的配置;
(3)非阻塞、高并發(fā)連接:數(shù)據(jù)復(fù)制時(shí),磁盤(pán)I/O的第一階段是非阻塞的。官方測(cè)試能夠支撐5萬(wàn)并發(fā)連接,在實(shí)際生產(chǎn)環(huán)境中跑到2~3萬(wàn)并發(fā)連接數(shù)。(這得益于Nginx使用了最新的epoll模型);
PS:對(duì)于一個(gè)Web服務(wù)器來(lái)說(shuō),首先看一個(gè)請(qǐng)求的基本過(guò)程:建立連接---接收數(shù)據(jù)---發(fā)送數(shù)據(jù),在系統(tǒng)底層看來(lái) :上述過(guò)程(建立連接---接收數(shù)據(jù)---發(fā)送數(shù)據(jù))在系統(tǒng)底層就是讀寫(xiě)事件。
①如果采用阻塞調(diào)用的方式,當(dāng)讀寫(xiě)事件沒(méi)有準(zhǔn)備好時(shí),必然不能夠進(jìn)行讀寫(xiě)事件,那么久只好等待,等事件準(zhǔn)備好了,才能進(jìn)行讀寫(xiě)事件,那么請(qǐng)求就會(huì)被耽擱 。
②既然沒(méi)有準(zhǔn)備好阻塞調(diào)用不行,那么采用非阻塞調(diào)用方式。非阻塞就是:事件馬上返回,告訴你事件還沒(méi)準(zhǔn)備好呢,你慌什么,過(guò)會(huì)再來(lái)吧。好吧,你過(guò)一會(huì),再來(lái)檢查一下事件,直到事件準(zhǔn)備好了為止,在這期間,你就可以先去做其它事情,然后再來(lái)看看事件好了沒(méi)。雖然不阻塞了,但你得不時(shí)地過(guò)來(lái)檢查一下事件的狀態(tài),你可以做更多的事情了,但帶來(lái)的開(kāi)銷(xiāo)也是不小的。
(4)事件驅(qū)動(dòng):通信機(jī)制采用epoll模型,支持更大的并發(fā)連接。
①非阻塞通過(guò)不斷檢查事件的狀態(tài)來(lái)判斷是否進(jìn)行讀寫(xiě)操作,這樣帶來(lái)的開(kāi)銷(xiāo)很大,因此就有了異步非阻塞的事件處理機(jī)制。這種機(jī)制讓你可以同時(shí)監(jiān)控多個(gè)事件,調(diào)用他們是阻塞的,但可以設(shè)置超時(shí)時(shí)間,在超時(shí)時(shí)間之內(nèi),如果有事件準(zhǔn)備好了,就返回。這種機(jī)制解決了上面阻塞調(diào)用與非阻塞調(diào)用的兩個(gè)問(wèn)題。
②以epoll模型為例:當(dāng)事件沒(méi)有準(zhǔn)備好時(shí),就放入epoll(隊(duì)列)里面。如果有事件準(zhǔn)備好了,那么就去處理;如果事件返回的是EAGAIN,那么繼續(xù)將其放入epoll里面。從而,只要有事件準(zhǔn)備好了,我們就去處理它,只有當(dāng)所有事件都沒(méi)有準(zhǔn)備好時(shí),才在epoll里面等著。這樣,我們就可以并發(fā)處理大量的并發(fā)了,當(dāng)然,這里的并發(fā)請(qǐng)求,是指未處理完的請(qǐng)求,線程只有一個(gè),所以同時(shí)能處理的請(qǐng)求當(dāng)然只有一個(gè)了,只是在請(qǐng)求間進(jìn)行不斷地切換而已,切換也是因?yàn)楫惒绞录礈?zhǔn)備好,而主動(dòng)讓出的。這里的切換是沒(méi)有任何代價(jià),你可以理解為循環(huán)處理多個(gè)準(zhǔn)備好的事件,事實(shí)上就是這樣的。
③與多線程方式相比,這種事件處理方式是有很大的優(yōu)勢(shì)的,不需要?jiǎng)?chuàng)建線程,每個(gè)請(qǐng)求占用的內(nèi)存也很少,沒(méi)有上下文切換,事件處理非常的輕量級(jí),并發(fā)數(shù)再多也不會(huì)導(dǎo)致無(wú)謂的資源浪費(fèi)(上下文切換)。對(duì)于IIS服務(wù)器,每個(gè)請(qǐng)求會(huì)獨(dú)占一個(gè)工作線程,當(dāng)并發(fā)數(shù)上到幾千時(shí),就同時(shí)有幾千的線程在處理請(qǐng)求了。這對(duì)操作系統(tǒng)來(lái)說(shuō),是個(gè)不小的挑戰(zhàn):因?yàn)榫程帶來(lái)的內(nèi)存占用非常大,線程的上下文切換帶來(lái)的cpu開(kāi)銷(xiāo)很大,自然性能就上不去,從而導(dǎo)致在高并發(fā)場(chǎng)景下性能下降嚴(yán)重。
總結(jié):通過(guò)異步非阻塞的事件處理機(jī)制,Nginx實(shí)現(xiàn)由進(jìn)程循環(huán)處理多個(gè)準(zhǔn)備好的事件,從而實(shí)現(xiàn)高并發(fā)和輕量級(jí)。
(5)Master/Worker結(jié)構(gòu):一個(gè)master進(jìn)程,生成一個(gè)或多個(gè)worker進(jìn)程。
PS:Master-Worker設(shè)計(jì)模式核心思想是將原來(lái)串行的邏輯并行化,并將邏輯拆分成很多獨(dú)立模塊并行執(zhí)行。其中主要包含兩個(gè)主要組件Master和Worker,Master主要將邏輯進(jìn)行拆分,拆分為互相獨(dú)立的部分,同時(shí)維護(hù)了Worker隊(duì)列,將每個(gè)獨(dú)立部分下發(fā)到多個(gè)Worker并行執(zhí)行,Worker主要進(jìn)行實(shí)際邏輯計(jì)算,并將結(jié)果返回給Master。
問(wèn):nginx采用這種進(jì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)程的異常退出,肯定是程序有bug了,異常退出,會(huì)導(dǎo)致當(dāng)前Worker上的所有請(qǐng)求失敗,不過(guò)不會(huì)影響到所有請(qǐng)求,所以降低了風(fēng)險(xiǎn)。
(6)內(nèi)存消耗小:處理大并發(fā)的請(qǐng)求內(nèi)存消耗非常小。在3萬(wàn)并發(fā)連接下,開(kāi)啟的10個(gè)Nginx 進(jìn)程才消耗150M內(nèi)存(15M*10=150M)。
(7)內(nèi)置的健康檢查功能:如果 Nginx 代理的后端的某臺(tái) Web 服務(wù)器宕機(jī)了,不會(huì)影響前端訪問(wèn)。
(8)節(jié)省帶寬:支持 GZIP 壓縮,可以添加瀏覽器本地緩存的 Header 頭。
(9)穩(wěn)定性高:用于反向代理,宕機(jī)的概率微乎其微。