<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          深入了解 Nginx!

          共 10433字,需瀏覽 21分鐘

           ·

          2021-04-10 10:33

          公眾號(hào)關(guān)注“杰哥的IT之旅”,

          選擇“星標(biāo)”,重磅干貨,第一時(shí)間送達(dá)!


          作者:小楊互聯(lián)網(wǎng) 侵權(quán)刪

          今天我們來(lái)談?wù)勈裁词荖ginx?

          什么是Nginx?

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

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

          Nginx (engine x) 是一個(gè)高性能的HTTP和反向代理web服務(wù)器,同時(shí)也提供了IMAP/POP3/SMTP服務(wù)。Nginx是由伊戈?duì)枴べ愃饕驗(yàn)槎砹_斯訪問(wè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是一款輕量級(jí)的Web 服務(wù)器/反向代理服務(wù)器及電子郵件(IMAP/POP3)代理服務(wù)器,在BSD-like 協(xié)議下發(fā)行。其特點(diǎn)是占有內(nèi)存少,并發(fā)能力強(qiáng),事實(shí)上nginx的并發(fā)能力在同類型的網(wǎng)頁(yè)服務(wù)器中表現(xiàn)較好,中國(guó)大陸使用nginx網(wǎng)站用戶有:百度、京東、新浪、網(wǎng)易、騰訊、淘寶等。

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

          Nginx 架構(gòu)原理

          反向代理

          概念

          反向代理(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ù)器。

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

          結(jié)論就是,反向代理服務(wù)器對(duì)于客戶端而言它就像是原始服務(wù)器,并且客戶端不需要進(jìn)行任何特別的設(shè)置。客戶端向反向代理的命名空間(name-space)中的內(nèi)容發(fā)送普通請(qǐng)求,接著反向代理服務(wù)器將判斷向何處(原始服務(wù)器)轉(zhuǎn)交請(qǐng)求,并將獲得的內(nèi)容返回給客戶端,就像這些內(nèi)容原本就是它自己的一樣。

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

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

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

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

          反向代理VS正向代理:

          1.2 工作流程

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

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

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

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

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

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

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

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

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

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

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

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

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

          (4)解決Ajax跨域問(wèn)題;

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

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

          Nginx模塊

          Nginx有五大優(yōu)點(diǎn):模塊化、事件驅(qū)動(dòng)、異步、非阻塞、多進(jìn)程單線程。由內(nèi)核和模塊組成的,其中內(nèi)核完成的工作比較簡(jiǎn)單,僅僅通過(guò)查找配置文件將客戶端請(qǐng)求映射到一個(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(處理器模塊):此類模塊直接處理請(qǐng)求,并進(jìn)行輸出內(nèi)容和修改headers信息等操作。

          • Filters (過(guò)濾器模塊):此類模塊主要對(duì)其他處理器模塊輸出的內(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)針對(duì)特定應(yīng)用的一系列候選模塊。其他模塊負(fù)責(zé)分配給web服務(wù)器的實(shí)際工作:

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

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

          模塊處理

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

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

          • OK

          • ERROR

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

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

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

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

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

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

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

          過(guò)濾模塊鏈的特別之處在于:

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

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

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

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

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

          • 客戶端發(fā)送HTTP請(qǐng)求 –>

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

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

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

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

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

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

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

          Nginx本身做的工作實(shí)際很少,當(dāng)它接到一個(gè)HTTP請(qǐng)求時(shí),它僅僅是通過(guò)查找配置文件將此次請(qǐng)求映射到一個(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é)處理請(qǐng)求,完成響應(yīng)內(nèi)容的生成,而filter模塊對(duì)響應(yīng)內(nèi)容進(jìn)行處理。

          Nginx請(qǐng)求處理

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

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

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

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

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

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

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

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

          Nginx如何做到熱部署?

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

          通過(guò)上文我們已經(jīng)知道worker進(jìn)程負(fù)責(zé)處理具體的請(qǐng)求,那么如果想達(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)行處理請(qǐng)求,而且新的請(qǐng)求必須都交給新的worker進(jìn)程,至于老的worker進(jìn)程,等把那些以前的請(qǐng)求處理完畢后,kill掉即可。

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

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

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

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

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

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

          Nginx掛了怎么辦?

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

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

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

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

          第一:請(qǐng)求不要直接打到Nginx上,應(yīng)該先通過(guò)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故障切換)

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

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

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

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

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

          • 處理 request 的 header 和 body。

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

          • 完成 request 的處理。

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

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

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

          首先,master進(jìn)程一開始就會(huì)根據(jù)我們的配置,來(lái)建立需要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è)請(qǐng)求進(jìn)來(lái)的時(shí)候,所有的worker都會(huì)感知到。這樣就會(huì)產(chǎn)生所謂的“驚群現(xiàn)象”。為了保證只會(huì)有一個(gè)進(jìn)程成功注冊(cè)到listenfd的讀事件,nginx中實(shí)現(xiàn)了一個(gè)“accept_mutex”類似互斥鎖,只有獲取到這個(gè)鎖的進(jìn)程,才可以去注冊(cè)讀事件。其他進(jìn)程全部accept 失敗。

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

          進(jìn)程模型的處理方式帶來(lái)的一些好處就是:進(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è)問(wèn)題;并且還因此避免的多線程的上下文切換導(dǎo)致的性能損失。

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

          針對(duì)這種現(xiàn)象,Nginx采用了一個(gè)是否打開accept_mutex選項(xiàng)的值,ngx_accept_disabled標(biāo)識(shí)控制一個(gè)worker進(jìn)程是否需要去競(jìng)爭(zhēng)獲取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,自己的連接就控制下來(lái)了,其它進(jìn)程的連接池就會(huì)得到利用,這樣,nginx就控制了多進(jìn)程間連接的平衡了。

          一個(gè)簡(jiǎn)單的HTTP請(qǐng)求

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

          • 初始化 HTTP Request(讀取來(lái)自客戶端的數(shù)據(jù),生成 HTTP Request 對(duì)象,該對(duì)象含有該請(qǐng)求所有的信息)。

          • 處理請(qǐng)求頭。

          • 處理請(qǐng)求體。

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

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

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

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

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

          通常情況下,一個(gè) phase handler 對(duì)這個(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è)請(qǐng)求關(guān)聯(lián)的虛擬主機(jī)的配置。如果找到了這個(gè)虛擬主機(jī)的配置,那么通常情況下,這個(gè) HTTP Request 將會(huì)經(jīng)過(guò)以下幾個(gè)階段的處理(phase handlers):

          • NGX_HTTP_POST_READ_PHASE: 讀取請(qǐng)求內(nèi)容階段

          • NGX_HTTP_SERVER_REWRITE_PHASE: Server 請(qǐng)求地址重寫階段

          • NGX_HTTP_FIND_CONFIG_PHASE: 配置查找階段

          • NGX_HTTP_REWRITE_PHASE: Location請(qǐng)求地址重寫階段

          • NGX_HTTP_POST_REWRITE_PHASE: 請(qǐng)求地址重寫提交階段

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

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

          • NGX_HTTP_POST_ACCESS_PHASE: 訪問(wèn)權(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 對(duì)應(yīng)的 location 在配置文件中被明確指定了一個(gè) content handler,那么Nginx 就可以通過(guò)對(duì) location 的匹配,直接找到這個(gè)對(duì)應(yīng)的 handler,并把這個(gè) request 交給這個(gè) content handler 去處理。這樣的配置指令包括像,perl,flv,proxy_pass,mp4等。

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

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

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

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

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

          • 請(qǐng)求的 URI 如果對(duì)應(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)用的順序依次說(shuō)明如下:

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

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

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

          請(qǐng)求完整處理過(guò)程

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

          推薦閱讀

          Nginx系列教程(一)| 手把手教你在Linux環(huán)境下搭建Nginx服務(wù)

          Nginx系列教程(二)| 一文帶你讀懂Nginx的正向與反向代理

          Nginx系列教程(三)| 一文帶你讀懂Nginx的負(fù)載均衡

          Nginx系列教程(四)| 一文帶你讀懂Nginx的動(dòng)靜分離

          Nginx系列教程(五)| 利用 Nginx+Keepalived 實(shí)現(xiàn)高可用技術(shù)

          Nginx系列教程(六)| 手把手教你搭建 LNMP 架構(gòu)并部署天空網(wǎng)絡(luò)電影系統(tǒng)

          淺談 Nginx 性能調(diào)優(yōu)

          【建議收藏】神器 Nginx 的學(xué)習(xí)手冊(cè)

          Nginx從入門到干活,看這一篇足矣

          Nginx 在運(yùn)維領(lǐng)域中的應(yīng)用,看這一篇就夠了

          Nginx 這個(gè)功能厲害了!

          瀏覽 46
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五月天六月色婷婷在线 | 精品久久久久99水蜜桃 | 亚洲热在线观看 | 使劲操我视频 | 久久久中文字幕三级电影网 |