0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一文帶你深入了解 Nginx!

Linux愛好者 ? 來源:小楊互聯(lián)網(wǎng) ? 作者:小楊互聯(lián)網(wǎng) ? 2021-05-13 15:01 ? 次閱讀

今天我們來談?wù)勈裁词荖ginx?

什么是Nginx?

Nginx代碼完全用C語言從頭寫成,已經(jīng)移植到許多體系結(jié)構(gòu)和操作系統(tǒng),包括:Linux、FreeBSD、Solaris、Mac OS X、AIX以及Microsoft Windows。

Nginx有自己的函數(shù)庫,并且除了zlib、PCRE和OpenSSL之外,標(biāo)準(zhǔn)模塊只使用系統(tǒng)C庫函數(shù)。而且,如果不需要或者考慮到潛在的授權(quán)沖突,可以不使用這些第三方庫

Nginx (engine x) 是一個(gè)高性能的HTTP和反向代理web服務(wù)器,同時(shí)也提供了IMAP/POP3/SMTP服務(wù)。Nginx是由伊戈?duì)枴べ愃饕驗(yàn)槎砹_斯訪問量第二的Rambler.ru站點(diǎn)(俄文:Рамблер)開發(fā)的,第一個(gè)公開版本0.1.0發(fā)布于2004年10月4日。

其將源代碼以類BSD許可證的形式發(fā)布,因它的穩(wěn)定性、豐富的功能集、示例配置文件和低系統(tǒng)資源的消耗而聞名。2011年6月1日,nginx 1.0.4發(fā)布。

Nginx是一款輕量級的Web 服務(wù)器/反向代理服務(wù)器及電子郵件(IMAP/POP3)代理服務(wù)器,在BSD-like 協(xié)議下發(fā)行。其特點(diǎn)是占有內(nèi)存少,并發(fā)能力強(qiáng),事實(shí)上nginx的并發(fā)能力在同類型的網(wǎng)頁服務(wù)器中表現(xiàn)較好,中國大陸使用nginx網(wǎng)站用戶有:百度、京東、新浪、網(wǎng)易、騰訊、淘寶等。

一句話 Nginx 就是牛逼,成熟,穩(wěn)定 ,應(yīng)用范圍廣 主要還是開源。

Nginx 架構(gòu)原理

80facbd4-b3a2-11eb-bf61-12bb97331649.png

反向代理

概念

反向代理(Reverse Proxy)方式是指以代理服務(wù)器來接受internet上的連接請求,然后將請求轉(zhuǎn)發(fā)給內(nèi)部網(wǎng)絡(luò)上的服務(wù)器,并將從服務(wù)器上得到的結(jié)果返回給internet上請求連接的客戶端,此時(shí)代理服務(wù)器對外就表現(xiàn)為一個(gè)服務(wù)器。

舉個(gè)例子,比如我想訪問
http://www.test.com/readme,但www.test.com上并不存在readme頁面,于是他是偷偷從另外一臺(tái)服務(wù)器上取回來,然后作為自己的內(nèi)容返回用戶,但用戶并不知情。這里所提到的 www.test.com 這個(gè)域名對應(yīng)的服務(wù)器就設(shè)置了反向代理功能。

結(jié)論就是,反向代理服務(wù)器對于客戶端而言它就像是原始服務(wù)器,并且客戶端不需要進(jìn)行任何特別的設(shè)置??蛻舳讼蚍聪虼淼拿臻g(name-space)中的內(nèi)容發(fā)送普通請求,接著反向代理服務(wù)器將判斷向何處(原始服務(wù)器)轉(zhuǎn)交請求,并將獲得的內(nèi)容返回給客戶端,就像這些內(nèi)容原本就是它自己的一樣。

正向代理,既然有反向代理,就肯定有正向代理。什么叫正向代理呢?

正向代理(Forward Proxy)通常都被簡稱為代理,就是在用戶無法正常訪問外部資源,比方說受到GFW的影響無法訪問twitter的時(shí)候,我們可以通過代理的方式,讓用戶繞過防火墻,從而連接到目標(biāo)網(wǎng)絡(luò)或者服務(wù)。

正向代理的工作原理就像一個(gè)跳板,比如:我訪問不了google.com,但是我能訪問一個(gè)代理服務(wù)器A,A能訪問google.com,于是我先連上代理服務(wù)器A,告訴他我需要google.com的內(nèi)容,A就去取回來,然后返回給我。從網(wǎng)站的角度,只在代理服務(wù)器來取內(nèi)容的時(shí)候有一次記錄,有時(shí)候并不知道是用戶的請求,也隱藏了用戶的資料,這取決于代理告不告訴網(wǎng)站。

結(jié)論就是,正向代理是一個(gè)位于客戶端和原始服務(wù)器(origin server)之間的服務(wù)器。為了從原始服務(wù)器取得內(nèi)容,客戶端向代理發(fā)送一個(gè)請求并指定目標(biāo)(原始服務(wù)器),然后代理向原始服務(wù)器轉(zhuǎn)交請求并將獲得的內(nèi)容返回給客戶端。

反向代理VS正向代理:

810baeea-b3a2-11eb-bf61-12bb97331649.png

81602a42-b3a2-11eb-bf61-12bb97331649.png

1.2 工作流程

用戶通過域名發(fā)出訪問Web服務(wù)器的請求,該域名被DNS服務(wù)器解析為反向代理服務(wù)器的IP地址;

反向代理服務(wù)器接受用戶的請求;

反向代理服務(wù)器在本地緩存中查找請求的內(nèi)容,找到后直接把內(nèi)容發(fā)送給用戶;

如果本地緩存里沒有用戶所請求的信息內(nèi)容,反向代理服務(wù)器會(huì)代替用戶向源服務(wù)器請求同樣的信息內(nèi)容,并把信息內(nèi)容發(fā)給用戶,如果信息內(nèi)容是緩存的還會(huì)把它保存到緩存中。

1.3 優(yōu)點(diǎn)

保護(hù)了真實(shí)的web服務(wù)器,保證了web服務(wù)器的資源安全

通常的代理服務(wù)器,只用于代理內(nèi)部網(wǎng)絡(luò)對Internet外部網(wǎng)絡(luò)的連接請求,客戶機(jī)必須指定代理服務(wù)器,并將本來要直接發(fā)送到Web服務(wù)器上的http請求發(fā)送到代理服務(wù)器中。不支持外部網(wǎng)絡(luò)對內(nèi)部網(wǎng)絡(luò)的連接請求,因?yàn)閮?nèi)部網(wǎng)絡(luò)對外部網(wǎng)絡(luò)是不可見的。當(dāng)一個(gè)代理服務(wù)器能夠代理外部網(wǎng)絡(luò)上的主機(jī),訪問內(nèi)部網(wǎng)絡(luò)時(shí),這種代理服務(wù)的方式稱為反向代理服務(wù)。此時(shí)代理服務(wù)器對外就表現(xiàn)為一個(gè)Web服務(wù)器,外部網(wǎng)絡(luò)就可以簡單把它當(dāng)作一個(gè)標(biāo)準(zhǔn)的Web服務(wù)器而不需要特定的配置。不同之處在于,這個(gè)服務(wù)器沒有保存任何網(wǎng)頁的真實(shí)數(shù)據(jù),所有的靜態(tài)網(wǎng)頁或者CGI程序,都保存在內(nèi)部的Web服務(wù)器上。因此對反向代理服務(wù)器的攻擊并不會(huì)使得網(wǎng)頁信息遭到破壞,這樣就增強(qiáng)了Web服務(wù)器的安全性。

節(jié)約了有限的IP地址資源

企業(yè)內(nèi)所有的網(wǎng)站共享一個(gè)在internet中注冊的IP地址,這些服務(wù)器分配私有地址,采用虛擬主機(jī)的方式對外提供服務(wù)。

減少WEB服務(wù)器壓力,提高響應(yīng)速度

反向代理就是通常所說的web服務(wù)器加速,它是一種通過在繁忙的web服務(wù)器和外部網(wǎng)絡(luò)之間增加一個(gè)高速的web緩沖服務(wù)器來降低實(shí)際的web服務(wù)器的負(fù)載的一種技術(shù)。反向代理是針對web服務(wù)器提高加速功能,作為代理緩存,它并不是針對瀏覽器用戶,而針對一臺(tái)或多臺(tái)特定的web服務(wù)器,它可以代理外部網(wǎng)絡(luò)對內(nèi)部網(wǎng)絡(luò)的訪問請求。

反向代理服務(wù)器會(huì)強(qiáng)制將外部網(wǎng)絡(luò)對要代理的服務(wù)器的訪問經(jīng)過它,這樣反向代理服務(wù)器負(fù)責(zé)接收客戶端的請求,然后到源服務(wù)器上獲取內(nèi)容,把內(nèi)容返回給用戶,并把內(nèi)容保存到本地,以便日后再收到同樣的信息請求時(shí),它會(huì)把本地緩存里的內(nèi)容直接發(fā)給用戶,以減少后端web服務(wù)器的壓力,提高響應(yīng)速度。因此Nginx還具有緩存功能。

其他優(yōu)點(diǎn)

(1)請求的統(tǒng)一控制,包括設(shè)置權(quán)限、過濾規(guī)則等;

(2)區(qū)分動(dòng)態(tài)和靜態(tài)可緩存內(nèi)容;

(3)實(shí)現(xiàn)負(fù)載均衡,內(nèi)部可以采用多臺(tái)服務(wù)器來組成服務(wù)器集群,外部還是可以采用一個(gè)地址訪問;

(4)解決Ajax跨域問題;

(5)作為真實(shí)服務(wù)器的緩沖,解決瞬間負(fù)載量大的問題;

(6)支持其他插件廣泛應(yīng)用 自帶豐富的庫文件lib 底層C語言編寫,所以異常強(qiáng)大。

Nginx模塊

Nginx有五大優(yōu)點(diǎn):模塊化、事件驅(qū)動(dòng)、異步、非阻塞、多進(jìn)程單線程。由內(nèi)核和模塊組成的,其中內(nèi)核完成的工作比較簡單,僅僅通過查找配置文件將客戶端請求映射到一個(gè)location block,然后又將這個(gè)location block中所配置的每個(gè)指令將會(huì)啟動(dòng)不同的模塊去完成相應(yīng)的工作。

模塊劃分

Nginx的模塊從結(jié)構(gòu)上分為核心模塊、基礎(chǔ)模塊和第三方模塊:

核心模塊:HTTP模塊、EVENT模塊和MAIL模塊

基礎(chǔ)模塊:HTTP Access模塊、HTTP FastCGI模塊、HTTP Proxy模塊和HTTP Rewrite模塊,

第三方模塊:HTTP Upstream Request Hash模塊、Notice模塊和HTTP Access Key模塊。

Nginx的模塊從功能上分為如下四類:

Core(核心模塊):構(gòu)建nginx基礎(chǔ)服務(wù)、管理其他模塊。

Handlers處理器模塊):此類模塊直接處理請求,并進(jìn)行輸出內(nèi)容和修改headers信息等操作。

Filters (過濾器模塊):此類模塊主要對其他處理器模塊輸出的內(nèi)容進(jìn)行修改操作,最后由Nginx輸出。

Proxies (代理類模塊):此類模塊是Nginx的HTTP Upstream之類的模塊,這些模塊主要與后端一些服務(wù)比如FastCGI等進(jìn)行交互,實(shí)現(xiàn)服務(wù)代理和負(fù)載均衡等功能。

Nginx的核心模塊主要負(fù)責(zé)建立nginx服務(wù)模型、管理網(wǎng)絡(luò)層和應(yīng)用層協(xié)議、以及啟動(dòng)針對特定應(yīng)用的一系列候選模塊。其他模塊負(fù)責(zé)分配給web服務(wù)器的實(shí)際工作:

當(dāng)Nginx發(fā)送文件或者轉(zhuǎn)發(fā)請求到其他服務(wù)器,由Handlers(處理模塊)或Proxies(代理類模塊)提供服務(wù);

當(dāng)需要Nginx把輸出壓縮或者在服務(wù)端加一些東西,由Filters(過濾模塊)提供服務(wù)。

模塊處理

1、當(dāng)服務(wù)器啟動(dòng),每個(gè)handlers(處理模塊)都有機(jī)會(huì)映射到配置文件中定義的特定位置(location);如果有多個(gè)handlers(處理模塊)映射到特定位置時(shí),只有一個(gè)會(huì)“贏”(說明配置文件有沖突項(xiàng),應(yīng)該避免發(fā)生)。

處理模塊以三種形式返回:

OK

ERROR

或者放棄處理這個(gè)請求而讓默認(rèn)處理模塊來處理(主要是用來處理一些靜態(tài)文件,事實(shí)上如果是位置正確而真實(shí)的靜態(tài)文件,默認(rèn)的處理模塊會(huì)搶先處理)

2、如果handlers(處理模塊)把請求反向代理到后端的服務(wù)器,就變成另外一類的模塊:load-balancers(負(fù)載均衡模塊)。負(fù)載均衡模塊的配置中有一組后端服務(wù)器,當(dāng)一個(gè)HTTP請求過來時(shí),它決定哪臺(tái)服務(wù)器應(yīng)當(dāng)獲得這個(gè)請求。

Nginx的負(fù)載均衡模塊采用兩種方法:

輪轉(zhuǎn)法,它處理請求就像紙牌游戲一樣從頭到尾分發(fā);

IP哈希法,在眾多請求的情況下,它確保來自同一個(gè)IP的請求會(huì)分發(fā)到相同的后端服務(wù)器。

3、如果handlers(處理模塊)沒有產(chǎn)生錯(cuò)誤,filters(過濾模塊)將被調(diào)用。多個(gè)filters(過濾模塊)能映射到每個(gè)位置,所以(比如)每個(gè)請求都可以被壓縮成塊。它們的執(zhí)行順序在編譯時(shí)決定。

filters(過濾模塊)是經(jīng)典的“接力鏈表(CHAIN OF RESPONSIBILITY)”模型:一個(gè)filters(過濾模塊)被調(diào)用,完成其工作,然后調(diào)用下一個(gè)filters(過濾模塊),直到最后一個(gè)filters(過濾模塊)。

過濾模塊鏈的特別之處在于:

每個(gè)filters(過濾模塊)不會(huì)等上一個(gè)filters(過濾模塊)全部完成;

它能把前一個(gè)過濾模塊的輸出作為其處理內(nèi)容;有點(diǎn)像Unix中的流水線;

過濾模塊能以buffer(緩沖區(qū))為單位進(jìn)行操作,這些buffer一般都是一頁(4K)大小,當(dāng)然你也可以在nginx.conf文件中進(jìn)行配置。這意味著,比如,模塊可以壓縮來自后端服務(wù)器的響應(yīng),然后像流一樣的到達(dá)客戶端,直到整個(gè)響應(yīng)發(fā)送完成。

總之,過濾模塊鏈以流水線的方式高效率地向客戶端發(fā)送響應(yīng)信息。

所以總結(jié)下上面的內(nèi)容,一個(gè)典型的HTTP處理周期是這樣的:

客戶端發(fā)送HTTP請求 –>

Nginx基于配置文件中的位置選擇一個(gè)合適的處理模塊 ->

(如果有)負(fù)載均衡模塊選擇一臺(tái)后端服務(wù)器 –>

處理模塊進(jìn)行處理并把輸出緩沖放到第一個(gè)過濾模塊上 –>

第一個(gè)過濾模塊處理后輸出給第二個(gè)過濾模塊 –>

然后第二個(gè)過濾模塊又到第三個(gè) –>

依此類推 –> 最后把響應(yīng)發(fā)給客戶端。

下圖展示了Nginx模塊處理流程:

8193c3d4-b3a2-11eb-bf61-12bb97331649.png

Nginx本身做的工作實(shí)際很少,當(dāng)它接到一個(gè)HTTP請求時(shí),它僅僅是通過查找配置文件將此次請求映射到一個(gè)location block,而此location中所配置的各個(gè)指令則會(huì)啟動(dòng)不同的模塊去完成工作,因此模塊可以看做Nginx真正的勞動(dòng)工作者。通常一個(gè)location中的指令會(huì)涉及一個(gè)handler模塊和多個(gè)filter模塊(當(dāng)然,多個(gè)location可以復(fù)用同一個(gè)模塊)。handler模塊負(fù)責(zé)處理請求,完成響應(yīng)內(nèi)容的生成,而filter模塊對響應(yīng)內(nèi)容進(jìn)行處理。

Nginx請求處理

Nginx在啟動(dòng)時(shí)會(huì)以daemon形式在后臺(tái)運(yùn)行,采用多進(jìn)程+異步非阻塞IO事件模型來處理各種連接請求。多進(jìn)程模型包括一個(gè)master進(jìn)程,多個(gè)worker進(jìn)程,一般worker進(jìn)程個(gè)數(shù)是根據(jù)服務(wù)器CPU核數(shù)來決定的。master進(jìn)程負(fù)責(zé)管理Nginx本身和其他worker進(jìn)程。如下圖:

81a23130-b3a2-11eb-bf61-12bb97331649.png

Master進(jìn)程負(fù)責(zé)管理Nginx本身和其他worker進(jìn)程

81b5a49a-b3a2-11eb-bf61-12bb97331649.png

從上圖中可以很明顯地看到,4個(gè)worker進(jìn)程的父進(jìn)程都是master進(jìn)程,表明worker進(jìn)程都是從父進(jìn)程fork出來的,并且父進(jìn)程的ppid為1,表示其為daemon進(jìn)程。

需要說明的是,在nginx多進(jìn)程中,每個(gè)worker都是平等的,因此每個(gè)進(jìn)程處理外部請求的機(jī)會(huì)權(quán)重都是一致的。

Master進(jìn)程的作用是?

讀取并驗(yàn)證配置文件nginx.conf;管理worker進(jìn)程;

Worker進(jìn)程的作用是?

每一個(gè)Worker進(jìn)程都維護(hù)一個(gè)線程(避免線程切換),處理連接和請求;注意Worker進(jìn)程的個(gè)數(shù)由配置文件決定,一般和CPU個(gè)數(shù)相關(guān)(有利于進(jìn)程切換),配置幾個(gè)就有幾個(gè)Worker進(jìn)程。

Nginx如何做到熱部署?

所謂熱部署,就是配置文件nginx.conf修改后,不需要stop Nginx,不需要中斷請求,就能讓配置文件生效?。╪ginx -s reload 重新加載/nginx -t檢查配置/nginx -s stop)

通過上文我們已經(jīng)知道worker進(jìn)程負(fù)責(zé)處理具體的請求,那么如果想達(dá)到熱部署的效果,可以想象:

方案一:

修改配置文件nginx.conf后,主進(jìn)程master負(fù)責(zé)推送給woker進(jìn)程更新配置信息,woker進(jìn)程收到信息后,更新進(jìn)程內(nèi)部的線程信息。

方案二:

修改配置文件nginx.conf后,重新生成新的worker進(jìn)程,當(dāng)然會(huì)以新的配置進(jìn)行處理請求,而且新的請求必須都交給新的worker進(jìn)程,至于老的worker進(jìn)程,等把那些以前的請求處理完畢后,kill掉即可。

Nginx采用的就是方案二來達(dá)到熱部署的!

Nginx如何做到高并發(fā)下的高效處理?

上文已經(jīng)提及Nginx的worker進(jìn)程個(gè)數(shù)與CPU綁定、worker進(jìn)程內(nèi)部包含一個(gè)線程高效回環(huán)處理請求,這的確有助于效率,但這是不夠的。

作為專業(yè)的程序員,我們可以開一下腦洞:BIO/NIO/AIO、異步/同步、阻塞/非阻塞…

要同時(shí)處理那么多的請求,要知道,有的請求需要發(fā)生IO,可能需要很長時(shí)間,如果等著它,就會(huì)拖慢worker的處理速度。

Nginx采用了Linux的epoll模型,epoll模型基于事件驅(qū)動(dòng)機(jī)制,它可以監(jiān)控多個(gè)事件是否準(zhǔn)備完畢,如果OK,那么放入epoll隊(duì)列中,這個(gè)過程是異步的。worker只需要從epoll隊(duì)列循環(huán)處理即可。

Nginx掛了怎么辦?

Nginx既然作為入口網(wǎng)關(guān),很重要,如果出現(xiàn)單點(diǎn)問題,顯然是不可接受的。

答案是:Keepalived+Nginx實(shí)現(xiàn)高可用。

Keepalived是一個(gè)高可用解決方案,主要是用來防止服務(wù)器單點(diǎn)發(fā)生故障,可以通過和Nginx配合來實(shí)現(xiàn)Web服務(wù)的高可用。(其實(shí),Keepalived不僅僅可以和Nginx配合,還可以和很多其他服務(wù)配合)

Keepalived+Nginx實(shí)現(xiàn)高可用的思路:

第一:請求不要直接打到Nginx上,應(yīng)該先通過Keepalived(這就是所謂虛擬IP,VIP)

第二:Keepalived應(yīng)該能監(jiān)控Nginx的生命狀態(tài)(提供一個(gè)用戶自定義的腳本,定期檢查Nginx進(jìn)程狀態(tài),進(jìn)行權(quán)重變化,,從而實(shí)現(xiàn)Nginx故障切換)

可以通過其他工具做動(dòng)態(tài)負(fù)載均衡。

81e4f9ac-b3a2-11eb-bf61-12bb97331649.png

Nginx真正處理請求業(yè)務(wù)的是Worker之下的線程。worker進(jìn)程中有一個(gè)ngx_worker_process_cycle()函數(shù),執(zhí)行無限循環(huán),不斷處理收到的來自客戶端的請求,并進(jìn)行處理,直到整個(gè)Nginx服務(wù)被停止。

worker 進(jìn)程中,ngx_worker_process_cycle()函數(shù)就是這個(gè)無限循環(huán)的處理函數(shù)。在這個(gè)函數(shù)中,一個(gè)請求的簡單處理流程如下:

操作系統(tǒng)提供的機(jī)制(例如 epoll, kqueue 等)產(chǎn)生相關(guān)的事件。

接收和處理這些事件,如是接收到數(shù)據(jù),則產(chǎn)生更高層的 request 對象。

處理 request 的 header 和 body。

產(chǎn)生響應(yīng),并發(fā)送回客戶端。

完成 request 的處理。

重新初始化定時(shí)器及其他事件。

多進(jìn)程處理模型

下面來介紹一個(gè)請求進(jìn)來,多進(jìn)程模型的處理方式:

首先,master進(jìn)程一開始就會(huì)根據(jù)我們的配置,來建立需要listen的網(wǎng)絡(luò)socket fd,然后fork出多個(gè)worker進(jìn)程。

其次,根據(jù)進(jìn)程的特性,新建立的worker進(jìn)程,也會(huì)和master進(jìn)程一樣,具有相同的設(shè)置。因此,其也會(huì)去監(jiān)聽相同ip端口的套接字socket fd。

然后,這個(gè)時(shí)候有多個(gè)worker進(jìn)程都在監(jiān)聽同樣設(shè)置的socket fd,意味著當(dāng)有一個(gè)請求進(jìn)來的時(shí)候,所有的worker都會(huì)感知到。這樣就會(huì)產(chǎn)生所謂的“驚群現(xiàn)象”。為了保證只會(huì)有一個(gè)進(jìn)程成功注冊到listenfd的讀事件,nginx中實(shí)現(xiàn)了一個(gè)“accept_mutex”類似互斥鎖,只有獲取到這個(gè)鎖的進(jìn)程,才可以去注冊讀事件。其他進(jìn)程全部accept 失敗。

最后,監(jiān)聽成功的worker進(jìn)程,讀取請求,解析處理,響應(yīng)數(shù)據(jù)返回給客戶端,斷開連接,結(jié)束。因此,一個(gè)request請求,只需要worker進(jìn)程就可以完成。

進(jìn)程模型的處理方式帶來的一些好處就是:進(jìn)程之間是獨(dú)立的,也就是一個(gè)worker進(jìn)程出現(xiàn)異常退出,其他worker進(jìn)程是不會(huì)受到影響的;此外,獨(dú)立進(jìn)程也會(huì)避免一些不需要的鎖操作,這樣子會(huì)提高處理效率,并且開發(fā)調(diào)試也更容易。

如前文所述,多進(jìn)程模型+異步非阻塞模型才是勝出的方案。單純的多進(jìn)程模型會(huì)導(dǎo)致連接并發(fā)數(shù)量的降低,而采用異步非阻塞IO模型很好的解決了這個(gè)問題;并且還因此避免的多線程的上下文切換導(dǎo)致的性能損失。

worker進(jìn)程會(huì)競爭監(jiān)聽客戶端的連接請求:這種方式可能會(huì)帶來一個(gè)問題,就是可能所有的請求都被一個(gè)worker進(jìn)程給競爭獲取了,導(dǎo)致其他進(jìn)程都比較空閑,而某一個(gè)進(jìn)程會(huì)處于忙碌的狀態(tài),這種狀態(tài)可能還會(huì)導(dǎo)致無法及時(shí)響應(yīng)連接而丟棄discard掉本有能力處理的請求。這種不公平的現(xiàn)象,是需要避免的,尤其是在高可靠web服務(wù)器環(huán)境下。

針對這種現(xiàn)象,Nginx采用了一個(gè)是否打開accept_mutex選項(xiàng)的值,ngx_accept_disabled標(biāo)識(shí)控制一個(gè)worker進(jìn)程是否需要去競爭獲取accept_mutex選項(xiàng),進(jìn)而獲取accept事件。

ngx_accept_disabled值:nginx單進(jìn)程的所有連接總數(shù)的八分之一,減去剩下的空閑連接數(shù)量,得到的這個(gè)ngx_accept_disabled。

當(dāng)ngx_accept_disabled大于0時(shí),不會(huì)去嘗試獲取accept_mutex鎖,并且將ngx_accept_disabled減1,于是,每次執(zhí)行到此處時(shí),都會(huì)去減1,直到小于0。不去獲取accept_mutex鎖,就是等于讓出獲取連接的機(jī)會(huì),很顯然可以看出,當(dāng)空閑連接越少時(shí),ngx_accept_disable越大,于是讓出的機(jī)會(huì)就越多,這樣其它進(jìn)程獲取鎖的機(jī)會(huì)也就越大。不去accept,自己的連接就控制下來了,其它進(jìn)程的連接池就會(huì)得到利用,這樣,nginx就控制了多進(jìn)程間連接的平衡了。

一個(gè)簡單的HTTP請求

從 Nginx 的內(nèi)部來看,一個(gè) HTTP Request 的處理過程涉及到以下幾個(gè)階段:

初始化 HTTP Request(讀取來自客戶端的數(shù)據(jù),生成 HTTP Request 對象,該對象含有該請求所有的信息)。

處理請求頭。

處理請求體。

如果有的話,調(diào)用與此請求(URL 或者 Location)關(guān)聯(lián)的 handler。

依次調(diào)用各 phase handler 進(jìn)行處理。

在建立連接過程中,對于nginx監(jiān)聽到的每個(gè)客戶端連接,都會(huì)將它的讀事件的handler設(shè)置為ngx_http_init_request函數(shù),這個(gè)函數(shù)就是請求處理的入口。在處理請求時(shí),主要就是要解析http請求,比如:uri,請求行等,然后再根據(jù)請求生成響應(yīng)。下面看一下nginx處理的具體過程:

81f1738a-b3a2-11eb-bf61-12bb97331649.jpg

在這里,我們需要了解一下 phase handler 這個(gè)概念。phase 字面的意思,就是階段。所以 phase handlers 也就好理解了,就是包含若干個(gè)處理階段的一些 handler。

在每一個(gè)階段,包含有若干個(gè) handler,再處理到某個(gè)階段的時(shí)候,依次調(diào)用該階段的 handler 對 HTTP Request 進(jìn)行處理。

通常情況下,一個(gè) phase handler 對這個(gè) request 進(jìn)行處理,并產(chǎn)生一些輸出。通常 phase handler 是與定義在配置文件中的某個(gè) location 相關(guān)聯(lián)的。

一個(gè) phase handler 通常執(zhí)行以下幾項(xiàng)任務(wù):

獲取 location 配置。

產(chǎn)生適當(dāng)?shù)捻憫?yīng)。

發(fā)送 response header。

發(fā)送 response body。

當(dāng) Nginx 讀取到一個(gè) HTTP Request 的 header 的時(shí)候,Nginx 首先查找與這個(gè)請求關(guān)聯(lián)的虛擬主機(jī)的配置。如果找到了這個(gè)虛擬主機(jī)的配置,那么通常情況下,這個(gè) HTTP Request 將會(huì)經(jīng)過以下幾個(gè)階段的處理(phase handlers):

NGX_HTTP_POST_READ_PHASE: 讀取請求內(nèi)容階段

NGX_HTTP_SERVER_REWRITE_PHASE: Server 請求地址重寫階段

NGX_HTTP_FIND_CONFIG_PHASE: 配置查找階段

NGX_HTTP_REWRITE_PHASE: Location請求地址重寫階段

NGX_HTTP_POST_REWRITE_PHASE: 請求地址重寫提交階段

NGX_HTTP_PREACCESS_PHASE: 訪問權(quán)限檢查準(zhǔn)備階段

NGX_HTTP_ACCESS_PHASE: 訪問權(quán)限檢查階段

NGX_HTTP_POST_ACCESS_PHASE: 訪問權(quán)限檢查提交階段

NGX_HTTP_TRY_FILES_PHASE: 配置項(xiàng) try_files 處理階段

NGX_HTTP_CONTENT_PHASE: 內(nèi)容產(chǎn)生階段

NGX_HTTP_LOG_PHASE: 日志模塊處理階段

在內(nèi)容產(chǎn)生階段,為了給一個(gè) request 產(chǎn)生正確的響應(yīng),Nginx 必須把這個(gè) request 交給一個(gè)合適的 content handler 去處理。如果這個(gè) request 對應(yīng)的 location 在配置文件中被明確指定了一個(gè) content handler,那么Nginx 就可以通過對 location 的匹配,直接找到這個(gè)對應(yīng)的 handler,并把這個(gè) request 交給這個(gè) content handler 去處理。這樣的配置指令包括像,perl,flv,proxy_pass,mp4等。

如果一個(gè) request 對應(yīng)的 location 并沒有直接有配置的 content handler,那么 Nginx 依次嘗試:

如果一個(gè) location 里面有配置 random_index on,那么隨機(jī)選擇一個(gè)文件,發(fā)送給客戶端。

如果一個(gè) location 里面有配置 index 指令,那么發(fā)送 index 指令指明的文件,給客戶端。

如果一個(gè) location 里面有配置 autoindex on,那么就發(fā)送請求地址對應(yīng)的服務(wù)端路徑下的文件列表給客戶端。

如果這個(gè) request 對應(yīng)的 location 上有設(shè)置 gzip_static on,那么就查找是否有對應(yīng)的.gz文件存在,有的話,就發(fā)送這個(gè)給客戶端(客戶端支持 gzip 的情況下)。

請求的 URI 如果對應(yīng)一個(gè)靜態(tài)文件,static module 就發(fā)送靜態(tài)文件的內(nèi)容到客戶端。

內(nèi)容產(chǎn)生階段完成以后,生成的輸出會(huì)被傳遞到 filter 模塊去進(jìn)行處理。filter 模塊也是與 location 相關(guān)的。所有的 filter 模塊都被組織成一條鏈。輸出會(huì)依次穿越所有的 filter,直到有一個(gè) filter 模塊的返回值表明已經(jīng)處理完成。

這里列舉幾個(gè)常見的 filter 模塊,例如:

server-side includes。

XSLT filtering。

圖像縮放之類的。

gzip 壓縮。

在所有的 filter 中,有幾個(gè) filter 模塊需要關(guān)注一下。按照調(diào)用的順序依次說明如下:

copy: 將一些需要復(fù)制的 buf(文件或者內(nèi)存)重新復(fù)制一份然后交給剩余的 body filter 處理。

postpone: 這個(gè) filter 是負(fù)責(zé) subrequest 的,也就是子請求的。

write: 寫輸出到客戶端,實(shí)際上是寫到連接對應(yīng)的 socket 上。

請求完整處理過程

根據(jù)以上請求步驟所述,請求完整的處理過程如下圖所示:

821b5074-b3a2-11eb-bf61-12bb97331649.jpg

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • HTTP
    +關(guān)注

    關(guān)注

    0

    文章

    478

    瀏覽量

    30765
  • Filter
    +關(guān)注

    關(guān)注

    0

    文章

    48

    瀏覽量

    21052
  • nginx
    +關(guān)注

    關(guān)注

    0

    文章

    139

    瀏覽量

    12115

原文標(biāo)題:深入了解 Nginx!

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    深入了解PCI轉(zhuǎn)XMC載板轉(zhuǎn)接卡

    電子發(fā)燒友網(wǎng)站提供《深入了解PCI轉(zhuǎn)XMC載板轉(zhuǎn)接卡.docx》資料免費(fèi)下載
    發(fā)表于 09-06 14:35 ?0次下載

    深入了解 MEMS 振蕩器 溫度補(bǔ)償 MEMS 振蕩器 TC-MO

    深入了解 MEMS 振蕩器/溫度補(bǔ)償 MEMS 振蕩器(TC-MO)-μPower MO1534/MO1569/MO1576/MO8021
    的頭像 發(fā)表于 07-30 16:38 ?173次閱讀
    <b class='flag-5'>深入了解</b> MEMS 振蕩器 溫度補(bǔ)償 MEMS 振蕩器 TC-MO

    深入了解表面貼裝晶體諧振器DSX1210A

    深入了解表面貼裝晶體諧振器DSX1210A
    的頭像 發(fā)表于 07-25 14:27 ?221次閱讀
    <b class='flag-5'>深入了解</b>表面貼裝晶體諧振器DSX1210A

    深入了解恒溫晶體振蕩器DC5032AS

    深入了解恒溫晶體振蕩器DC5032AS
    的頭像 發(fā)表于 07-25 10:37 ?179次閱讀
    <b class='flag-5'>深入了解</b>恒溫晶體振蕩器DC5032AS

    小熊派官網(wǎng)正式上線 可深入了解小熊派的各款開發(fā)套件

    我們?yōu)槊?b class='flag-5'>一款開發(fā)板打造個(gè)開源社區(qū),讓每位開發(fā)者都能在這里找到歸屬感和靈感。通過官網(wǎng)對硬件、軟件、案例和教程的開源,大家可以深入了解小熊派的各款開發(fā)套件。
    的頭像 發(fā)表于 06-13 08:42 ?601次閱讀
    小熊派官網(wǎng)正式上線 可<b class='flag-5'>深入了解</b>小熊派的各款開發(fā)套件

    深入了解IEEE協(xié)會(huì):設(shè)備MAC地址申請指南

    在數(shù)字化浪潮中,設(shè)備之間的通信變得日益頻繁和重要。而在這個(gè)通信網(wǎng)絡(luò)中,每臺(tái)設(shè)備都需要個(gè)獨(dú)特的身份標(biāo)識(shí)來幫助大家有效識(shí)別設(shè)備信息,那就是MAC地址。本篇內(nèi)容,英利檢測將帶大家深入了解IEEE協(xié)會(huì)
    的頭像 發(fā)表于 05-09 17:20 ?357次閱讀
    <b class='flag-5'>深入了解</b>IEEE協(xié)會(huì):設(shè)備MAC地址申請指南

    5.8G WiFi和2.4G WiFi如何選擇?帶你深度了解

    在無線網(wǎng)絡(luò)的世界中,5.8GWiFi和2.4GWiFi作為兩種常見的無線通信技術(shù),各自具有獨(dú)特的特點(diǎn)和優(yōu)勢。本文將帶你深入了解這兩種技術(shù)的區(qū)別、優(yōu)勢以及適用場景,幫助你更好地選擇適合自己的無線通信
    的頭像 發(fā)表于 04-18 09:49 ?2230次閱讀
    5.8G WiFi和2.4G WiFi如何選擇?<b class='flag-5'>一</b><b class='flag-5'>文</b><b class='flag-5'>帶你</b>深度<b class='flag-5'>了解</b>

    拆解FPGA芯片,帶你深入了解其原理

    拆解FPGA芯片,帶你深入了解其原理 現(xiàn)場可編程門陣列(FPGA)可以實(shí)現(xiàn)任意數(shù)字邏輯,從微處理器到視頻生成器或加密礦機(jī),應(yīng)俱全。FPGA由許多邏輯模塊組成,每個(gè)邏輯模塊通常由觸發(fā)器和邏輯功能
    發(fā)表于 04-17 11:07

    S參數(shù):深入了解與實(shí)際應(yīng)用

    個(gè)無源二端口網(wǎng)絡(luò)為例,深入介紹S參數(shù)。信號在傳輸過程中會(huì)產(chǎn)生入射波和反射波,既有進(jìn)入端口的信號也有從端口中出來的信號。
    的頭像 發(fā)表于 01-23 11:20 ?707次閱讀
    S參數(shù):<b class='flag-5'>深入了解</b>與實(shí)際應(yīng)用

    深入了解Linux中vi命令的使用

    深入了解Linux中vi命令的使用 VI是款在Linux系統(tǒng)中使用的文本編輯器,它是款功能強(qiáng)大、靈活性高的編輯器。VI編輯器具有非常高效的命令行操作方式,并且在各個(gè)版本的Linux中都得到了廣泛
    的頭像 發(fā)表于 12-25 11:15 ?346次閱讀

    帶你了解 DAC

    了解 DAC
    的頭像 發(fā)表于 12-07 15:10 ?7968次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>文</b><b class='flag-5'>帶你</b><b class='flag-5'>了解</b> DAC

    深入了解 GaN 技術(shù)

    深入了解 GaN 技術(shù)
    的頭像 發(fā)表于 12-06 17:28 ?5903次閱讀
    <b class='flag-5'>深入了解</b> GaN 技術(shù)

    了解剛?cè)峤Y(jié)合制造過程

    了解剛?cè)峤Y(jié)合制造過程
    的頭像 發(fā)表于 12-04 16:22 ?557次閱讀

    了解 PCB 的有效導(dǎo)熱系數(shù)

    了解 PCB 的有效導(dǎo)熱系數(shù)
    的頭像 發(fā)表于 11-24 15:48 ?1595次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>文</b><b class='flag-5'>了解</b> PCB 的有效導(dǎo)熱系數(shù)

    Nginx 如何實(shí)現(xiàn)高性能低消耗

    Nginx具有豐富的模塊庫、靈活的配置、較低資源消耗等優(yōu)點(diǎn)。下面,我們深入Nginx的工作機(jī)制 1.
    的頭像 發(fā)表于 11-11 11:31 ?496次閱讀
    <b class='flag-5'>Nginx</b> 如何實(shí)現(xiàn)高性能低消耗