鍍金池/ 教程/ Linux/ Nginx架構(gòu)
Nginx安裝
Nginx內(nèi)容緩存
Nginx架構(gòu)
Nginx進(jìn)程和運(yùn)行時(shí)控制
Nginx配置虛擬機(jī)
Nginx從源碼構(gòu)建安裝配置
為什么需要Nginx?
Nginx配置文件
Nginx壓縮和解壓
Nginx+PHP7+MySQL5.7(LNMP)環(huán)境配置
Nginx反向代理
Nginx+PHP7源碼安裝配置
Nginx快速入門
Nginx的優(yōu)勢(shì)(優(yōu)點(diǎn))
Nginx教程
Nginx特性
Nginx配置Web服務(wù)器
Nginx配置日志
Nginx配置靜態(tài)內(nèi)容服務(wù)器
Nginx主要應(yīng)用場(chǎng)景(必讀)
Nginx安裝(從Linx包安裝)

Nginx架構(gòu)

處理并發(fā)連接的傳統(tǒng)的基于進(jìn)程或線程的模型涉及使用單獨(dú)的進(jìn)程或線程處理每個(gè)連接,并阻止網(wǎng)絡(luò)或輸入/輸出操作。 根據(jù)應(yīng)用,在內(nèi)存和CPU消耗方面可能非常低效。 產(chǎn)生一個(gè)單獨(dú)的進(jìn)程或線程需要準(zhǔn)備一個(gè)新的運(yùn)行時(shí)環(huán)境,包括分配堆和堆棧內(nèi)存,以及創(chuàng)建新的執(zhí)行上下文。 額外的CPU時(shí)間也用于創(chuàng)建這些項(xiàng)目,這可能會(huì)導(dǎo)致由于線程在過多的上下文切換上的轉(zhuǎn)機(jī)而導(dǎo)致性能下降。 所有這些并發(fā)癥都表現(xiàn)在較老的Web服務(wù)器架構(gòu)(如Apache)中。 這是提供豐富的一般應(yīng)用功能和優(yōu)化的服務(wù)器資源使用之間的一個(gè)折衷。

從一開始nginx就是一個(gè)專門的工具,可以實(shí)現(xiàn)更高性能,更密集和經(jīng)濟(jì)地使用服務(wù)器資源,同時(shí)實(shí)現(xiàn)網(wǎng)站的動(dòng)態(tài)發(fā)展,所以它采用了不同的模式。 它實(shí)際上受到各種操作系統(tǒng)中高級(jí)事件機(jī)制的不斷發(fā)展的啟發(fā)。發(fā)展結(jié)果變成是一個(gè)模塊化的,事件驅(qū)動(dòng)的,異步的,單線程的非阻塞架構(gòu)的nginx代碼基礎(chǔ)。

nginx大量使用復(fù)用和事件通知,并專門用于分離進(jìn)程的特定任務(wù)。 連接在有限數(shù)量的單線程進(jìn)程稱為工作(worker)的高效運(yùn)行循環(huán)中處理。 在每個(gè)工作(worker)中,nginx可以處理每秒數(shù)千個(gè)并發(fā)連接和請(qǐng)求。

代碼結(jié)構(gòu)

nginx工作(worker)碼包括核心和功能模塊。 nginx的核心是負(fù)責(zé)維護(hù)嚴(yán)格的運(yùn)行循環(huán),并在請(qǐng)求處理的每個(gè)階段執(zhí)行模塊代碼的適當(dāng)部分。 模塊構(gòu)成了大部分的演示和應(yīng)用層功能。 模塊讀取和寫入網(wǎng)絡(luò)和存儲(chǔ),轉(zhuǎn)換內(nèi)容,執(zhí)行出站過濾,應(yīng)用服務(wù)器端包含操作,并在代理啟動(dòng)時(shí)將請(qǐng)求傳遞給上游服務(wù)器。

nginx的模塊化架構(gòu)通常允許開發(fā)人員擴(kuò)展一組Web服務(wù)器功能,而無需修改nginx內(nèi)核。 nginx模塊略有不同,即核心模塊,事件模塊,階段處理程序,協(xié)議,可變處理程序,過濾器,上游和負(fù)載平衡器。nginx不支持動(dòng)態(tài)加載的模塊; 即在構(gòu)建階段將模塊與核心一起編譯。

在處理與接受,處理和管理網(wǎng)絡(luò)連接和內(nèi)容檢索相關(guān)的各種操作時(shí),nginx在基于Linux,Solaris和BSD的操作系統(tǒng)中使用事件通知機(jī)制和一些磁盤I/O性能增強(qiáng),如:kqueue,epoll, 和事件端口。 目標(biāo)是為操作系統(tǒng)提供盡可能多的提示,以便及時(shí)獲取入站和出站流量,磁盤操作,讀取或?qū)懭胩捉幼?,超時(shí)等異步反饋。 對(duì)于每個(gè)基于Unix的nginx運(yùn)行的操作系統(tǒng),大量?jī)?yōu)化了復(fù)用和高級(jí)I/O操作的不同方法的使用。

nginx架構(gòu)的高級(jí)概述如下圖所示 -

工作模式

如前所述,nginx不會(huì)為每個(gè)連接生成一個(gè)進(jìn)程或線程。 相反,工作(worker)進(jìn)程接受來自共享“l(fā)isten”套接字的新請(qǐng)求,并在每個(gè)工作(worker)內(nèi)執(zhí)行高效的運(yùn)行循環(huán),以處理每個(gè)工作(worker)中的數(shù)千個(gè)連接。 沒有專門的仲裁或分配與nginx工作(worker)的聯(lián)系; 這個(gè)工作(worker)是由操作系統(tǒng)內(nèi)核機(jī)制完成的。 啟動(dòng)后,將創(chuàng)建一組初始偵聽套接字。 然后,工作(worker)在處理HTTP請(qǐng)求和響應(yīng)時(shí)不斷接受,讀取和寫入套接字。

運(yùn)行循環(huán)是nginx工作(worker)代碼中最復(fù)雜的部分。 它包括全面的內(nèi)部調(diào)用,并且在很大程度上依賴異步任務(wù)處理的想法。 異步操作通過模塊化,事件通知,廣泛使用回調(diào)函數(shù)和微調(diào)定時(shí)器來實(shí)現(xiàn)。 總體而言,關(guān)鍵原則是盡可能不阻塞。 nginx仍然可以阻塞的唯一情況是工作(worker)進(jìn)程沒有足夠的磁盤存儲(chǔ)。

由于nginx不會(huì)連接一個(gè)進(jìn)程或線程,所以在絕大多數(shù)情況下,內(nèi)存使用非常保守,非常有效。 nginx也節(jié)省CPU周期,因?yàn)檫M(jìn)程或線程沒有持續(xù)的創(chuàng)建 - 銷毀模式。 nginx的作用是檢查網(wǎng)絡(luò)和存儲(chǔ)的狀態(tài),初始化新連接,將其添加到運(yùn)行循環(huán)中,并異步處理直到完成,此時(shí)連接被重新分配并從運(yùn)行循環(huán)中刪除。 結(jié)合仔細(xì)使用系統(tǒng)調(diào)用(syscall)和精確實(shí)現(xiàn)支持接口(如poolslab內(nèi)存分配器),nginx通??梢栽跇O端工作負(fù)載下實(shí)現(xiàn)中到低的CPU使用。

在一些磁盤使用和CPU負(fù)載模式,應(yīng)調(diào)整nginx工作(worker)的數(shù)量。 在這里說一點(diǎn)基礎(chǔ)規(guī)則:系統(tǒng)管理員應(yīng)該為其工作負(fù)載嘗試幾個(gè)配置。 一般建議可能如下:如果負(fù)載模式是CPU密集型的,例如,處理大量TCP/IP,執(zhí)行SSL或壓縮,則nginx工作(worker)的數(shù)量應(yīng)與CPU內(nèi)核數(shù)量相匹配; 如果負(fù)載大多是磁盤I/O綁定,例如,從存儲(chǔ)或重代理服務(wù)不同的內(nèi)容集合 - 工作(worker)的數(shù)量可能是核心數(shù)量的一到兩倍。有些工程師會(huì)根據(jù)個(gè)人存儲(chǔ)單元的數(shù)量選擇工作(worker)的數(shù)量,但這種方法的效率取決于磁盤存儲(chǔ)的類型和配置。

nginx的開發(fā)人員將在即將推出的版本中解決的一個(gè)主要問題是如何避免磁盤I/O上的大多數(shù)阻塞。 目前,如果沒有足夠的存儲(chǔ)性能來提供特定工作(worker)生成的磁盤操作,該工作(worker)可能仍然阻止從磁盤讀取/寫入。 存在許多機(jī)制和配置文件指令來減輕此類磁盤I/O阻塞情況。要注意的是,諸如:sendfile和AIO之類的選項(xiàng)的組合通常會(huì)為磁盤性能帶來很大的余量。 應(yīng)該根據(jù)數(shù)據(jù)集,可用于nginx的內(nèi)存量和底層存儲(chǔ)架構(gòu)來規(guī)劃安裝一個(gè)nginx服務(wù)器。

現(xiàn)有工作(worker)模式的另一個(gè)問題是與嵌入式腳本的有限支持有關(guān)。 一個(gè)使用標(biāo)準(zhǔn)的nginx分發(fā),只支持嵌入Perl腳本。一個(gè)簡(jiǎn)單的解釋:關(guān)鍵問題是嵌入式腳本阻止任何操作或意外退出的可能性。 這兩種類型的行為將立即導(dǎo)致工作(worker)掛起的情況,同時(shí)影響到數(shù)千個(gè)連接。 更多的工作(worker)計(jì)劃是使nginx的嵌入式腳本更簡(jiǎn)單,更可靠,適用于更廣泛的應(yīng)用。

nginx進(jìn)程角色

nginx在內(nèi)存中運(yùn)行多個(gè)進(jìn)程; 有一個(gè)主進(jìn)程和幾個(gè)工作(worker)進(jìn)程。 還有一些特殊用途的過程,特別是緩存加載器和緩存管理器。 所有進(jìn)程都是單線程版本為1.x的nginx。 所有進(jìn)程主要使用共享內(nèi)存機(jī)制進(jìn)行進(jìn)程間通信。主進(jìn)程作為root用戶運(yùn)行。 緩存加載器,緩存管理器和工作(worker)則以無權(quán)限用戶運(yùn)行。

主程序負(fù)責(zé)以下任務(wù):

  • 讀取和驗(yàn)證配置
  • 創(chuàng)建,綁定和關(guān)閉套接字
  • 啟動(dòng),終止和維護(hù)配置的工作(worker)進(jìn)程數(shù)
  • 重新配置,無需中斷服務(wù)
  • 控制不間斷的二進(jìn)制升級(jí)(如果需要,啟動(dòng)新的二進(jìn)制并回滾)
  • 重新打開日志文件
  • 編譯嵌入式Perl腳本

工作(worker)進(jìn)程接受,處理和處理來自客戶端的連接,提供反向代理和過濾功能,并執(zhí)行幾乎所有其他的nginx能力。 關(guān)于監(jiān)視nginx實(shí)例的行為,系統(tǒng)管理員應(yīng)該關(guān)注工作(worker)進(jìn)程,因?yàn)樗鼈兪欠从砏eb服務(wù)器實(shí)際日常操作的過程。

緩存加載器進(jìn)程負(fù)責(zé)檢查磁盤緩存項(xiàng)目,并使用緩存元數(shù)據(jù)填充nginx的內(nèi)存數(shù)據(jù)庫。 本質(zhì)上,緩存加載器準(zhǔn)備nginx實(shí)例來處理已經(jīng)存儲(chǔ)在磁盤上的特定分配的目錄結(jié)構(gòu)中的文件。 它遍歷目錄,檢查緩存內(nèi)容元數(shù)據(jù),更新共享內(nèi)存中的相關(guān)條目,然后在所有內(nèi)容清潔并準(zhǔn)備使用時(shí)退出。
緩存管理器主要負(fù)責(zé)緩存到期和無效。 在正常的nginx操作期間它保持在內(nèi)存中,并且在失敗的情況下由主進(jìn)程重新啟動(dòng)。

nginx緩存簡(jiǎn)介

在nginx中的緩存以文件系統(tǒng)上的分層數(shù)據(jù)存儲(chǔ)的形式實(shí)現(xiàn)。 緩存密鑰是可配置的,并且可以使用不同的請(qǐng)求特定參數(shù)來控制進(jìn)入緩存的內(nèi)容。 緩存密鑰和緩存元數(shù)據(jù)存儲(chǔ)在共享存儲(chǔ)器段中,高速緩存加載器,緩存管理器和工作(worker)可以訪問它們。 目前,除了操作系統(tǒng)的虛擬文件系統(tǒng)機(jī)制暗示的優(yōu)化之外,沒有任何內(nèi)存中的文件緩存。 每個(gè)緩存的響應(yīng)都放在文件系統(tǒng)上的不同文件中。 層次結(jié)構(gòu)(級(jí)別和命名細(xì)節(jié))通過nginx配置指令進(jìn)行控制。 當(dāng)響應(yīng)寫入緩存目錄結(jié)構(gòu)時(shí),文件的路徑和名稱將從代理URL的MD5哈希導(dǎo)出。

將內(nèi)容放置在緩存中的過程如下:當(dāng)nginx從上游服務(wù)器讀取響應(yīng)時(shí),內(nèi)容首先寫入緩存目錄結(jié)構(gòu)之外的臨時(shí)文件。 當(dāng)nginx完成處理請(qǐng)求時(shí),它重命名臨時(shí)文件并將其移動(dòng)到緩存目錄。 如果用于代理的臨時(shí)文件目錄位于另一個(gè)文件系統(tǒng)上,則該文件將被復(fù)制,因此建議將臨時(shí)文件目錄和緩存目錄保存在同一文件系統(tǒng)上。 當(dāng)需要顯式清除緩存目錄結(jié)構(gòu)時(shí),從文件中刪除文件也是非常安全的。 nginx有第三方擴(kuò)展,可以遠(yuǎn)程控制緩存的內(nèi)容,還有更多的工作計(jì)劃將此功能集成到主分發(fā)中。