浅谈Nginx服务器的内部核心架构设计
前言
Nginx 是一個(gè) 免費(fèi)的,開(kāi)源的,高性能 的 HTTP 服務(wù)器和 反向代理,以及 IMAP / POP3 代理服務(wù)器。 Nginx 以其高性能,穩(wěn)定性,豐富的功能,簡(jiǎn)單的配置和低資源消耗而聞名。Nginx是一個(gè) Web 服務(wù)器,也可以用作 反向代理,負(fù)載均衡器 和 HTTP 緩存。
很多高知名度的網(wǎng)站都使用 Nginx,如:Netflix,GitHub,SoundCloud,MaxCDN 等。
?
?
?
正文
1. Nginx的整體架構(gòu)
?
?
?
1.1. 主進(jìn)程
Nginx 啟動(dòng)時(shí),會(huì)生成兩種類型的 進(jìn)程*,一個(gè)是 主進(jìn)程(master),一個(gè)(windows 版本的目前只有一個(gè))或 多個(gè)工作進(jìn)程(worker)。主進(jìn)程 并不處理網(wǎng)絡(luò)請(qǐng)求,主要負(fù)責(zé) 調(diào)度工作進(jìn)程,也就是圖示的 3 項(xiàng):加載配置、啟動(dòng)工作進(jìn)程 及 非停升級(jí)。所以,Nginx 啟動(dòng)以后,查看操作系統(tǒng)的進(jìn)程列表,我們就能看到 至少有兩個(gè) Nginx 進(jìn)程。
1.2. 工作進(jìn)程
服務(wù)器實(shí)際 處理網(wǎng)絡(luò)請(qǐng)求 及 響應(yīng) 的是 工作進(jìn)程(worker),在類 unix 系統(tǒng)上,Nginx 可以配置 多個(gè) worker,而每個(gè) worker 進(jìn)程 都可以同時(shí)處理 數(shù)以千計(jì) 的 網(wǎng)絡(luò)請(qǐng)求。
1.3. 模塊化設(shè)計(jì)
Nginx 的 worker 進(jìn)程,包括 核心 和 功能性模塊,核心模塊 負(fù)責(zé)維持一個(gè) 運(yùn)行循環(huán)(run-loop),執(zhí)行網(wǎng)絡(luò)請(qǐng)求處理的 不同階段 的模塊功能,比如:網(wǎng)絡(luò)讀寫(xiě)、存儲(chǔ)讀寫(xiě)、內(nèi)容傳輸、外出過(guò)濾,以及 將請(qǐng)求發(fā)往上游服務(wù)器 等。而其代碼的 模塊化設(shè)計(jì),也使得我們可以根據(jù)需要對(duì) 功能模塊 進(jìn)行適當(dāng)?shù)?選擇 和 修改,編譯成具有 特定功能 的服務(wù)器。
1.4. 事件驅(qū)動(dòng)模型
基于 異步及非阻塞 的 事件驅(qū)動(dòng)模型,可以說(shuō)是 Nginx 得以獲得 高并發(fā)、高性能 的關(guān)鍵因素,同時(shí)也得益于對(duì) Linux、Solaris 及類 BSD 等操作系統(tǒng)內(nèi)核中 事件通知 及 I/O 性能增強(qiáng)功能 的采用,如 kqueue、epoll 及 event ports。
1.5. 代理(proxy)設(shè)計(jì)
代理設(shè)計(jì),可以說(shuō)是 Nginx 深入骨髓的設(shè)計(jì),無(wú)論是對(duì)于 HTTP,還是對(duì)于 FastCGI、Memcache、Redis 等的網(wǎng)絡(luò)請(qǐng)求或響應(yīng),本質(zhì)上都采用了 代理機(jī)制。所以,Nginx 天生就是高性能的 代理服務(wù)器。
2. Nginx的模塊化設(shè)計(jì)
高度模塊化 的設(shè)計(jì)是 Nginx 的架構(gòu)基礎(chǔ)。Nginx 服務(wù)器被分解為 多個(gè)模塊,每個(gè)模塊就是一個(gè) 功能模塊,只負(fù)責(zé)自身的功能,模塊之間嚴(yán)格遵循 “高內(nèi)聚,低耦合” 的原則。
?
?
?
2.1. 核心模塊
核心模塊 是 Nginx 服務(wù)器正常運(yùn)行 必不可少 的模塊,提供 錯(cuò)誤日志記錄、配置文件解析、事件驅(qū)動(dòng)機(jī)制、進(jìn)程管理 等核心功能。
2.2. 標(biāo)準(zhǔn)HTTP模塊
標(biāo)準(zhǔn) HTTP 模塊提供 HTTP 協(xié)議解析相關(guān)的功能,比如:端口配置、網(wǎng)頁(yè)編碼設(shè)置、HTTP 響應(yīng)頭設(shè)置 等等。
2.3. 可選HTTP模塊
可選 HTTP 模塊主要用于 擴(kuò)展 標(biāo)準(zhǔn)的 HTTP 功能,讓 Nginx 能處理一些特殊的服務(wù),比如:Flash 多媒體傳輸、解析 GeoIP 請(qǐng)求、網(wǎng)絡(luò)傳輸壓縮、安全協(xié)議 SSL 支持等。
2.4. 郵件服務(wù)模塊
郵件服務(wù)模塊 主要用于支持 Nginx 的 郵件服務(wù),包括對(duì) POP3 協(xié)議、IMAP 協(xié)議和 SMTP 協(xié)議的支持。
2.5. 第三方模塊
第三方模塊 是為了擴(kuò)展 Nginx 服務(wù)器應(yīng)用,完成開(kāi)發(fā)者自定義功能,比如:Json 支持、Lua 支持等。
3. Nginx的請(qǐng)求方式處理
Nginx 是一個(gè) 高性能 的 Web 服務(wù)器,能夠同時(shí)處理 大量的并發(fā)請(qǐng)求。它結(jié)合 多進(jìn)程機(jī)制 和 異步機(jī)制,異步機(jī)制使用的是 異步非阻塞方式,接下來(lái)就給大家介紹一下 Nginx 的 多線程機(jī)制 和 異步非阻塞機(jī)制。
3.1. 多進(jìn)程機(jī)制
服務(wù)器每當(dāng)收到一個(gè)客戶端時(shí),就有 服務(wù)器主進(jìn)程(master process)生成一個(gè) 子進(jìn)程(worker process)出來(lái)和客戶端建立連接進(jìn)行交互,直到連接斷開(kāi),該子進(jìn)程就結(jié)束了。
使用 進(jìn)程 的好處是 各個(gè)進(jìn)程之間相互獨(dú)立,不需要加鎖,減少了使用鎖對(duì)性能造成影響,同時(shí)降低編程的復(fù)雜度,降低開(kāi)發(fā)成本。其次,采用獨(dú)立的進(jìn)程,可以讓 進(jìn)程互相之間不會(huì)影響,如果一個(gè)進(jìn)程發(fā)生異常退出時(shí),其它進(jìn)程正常工作,master 進(jìn)程則很快啟動(dòng)新的 worker 進(jìn)程,確保服務(wù)不會(huì)中斷,從而將風(fēng)險(xiǎn)降到最低。
缺點(diǎn)是操作系統(tǒng)生成一個(gè) 子進(jìn)程 需要進(jìn)行 內(nèi)存復(fù)制 等操作,在 資源 和 時(shí)間 上會(huì)產(chǎn)生一定的開(kāi)銷。當(dāng)有 大量請(qǐng)求 時(shí),會(huì)導(dǎo)致 系統(tǒng)性能下降。
3.2. 異步非阻塞機(jī)制
每個(gè) 工作進(jìn)程 使用 異步非阻塞方式,可以處理 多個(gè)客戶端請(qǐng)求。
當(dāng)某個(gè) 工作進(jìn)程 接收到客戶端的請(qǐng)求以后,調(diào)用 IO 進(jìn)行處理,如果不能立即得到結(jié)果,就去 處理其他請(qǐng)求(即為 非阻塞);而 客戶端 在此期間也 無(wú)需等待響應(yīng),可以去處理其他事情(即為 異步)。
當(dāng) IO 返回時(shí),就會(huì)通知此 工作進(jìn)程;該進(jìn)程得到通知,暫時(shí) 掛起 當(dāng)前處理的事務(wù)去 響應(yīng)客戶端請(qǐng)求。
4. Nginx事件驅(qū)動(dòng)模型
在 Nginx 的 異步非阻塞機(jī)制 中,工作進(jìn)程 在調(diào)用 IO 后,就去處理其他的請(qǐng)求,當(dāng) IO 調(diào)用返回后,會(huì) 通知 該 工作進(jìn)程。對(duì)于這樣的系統(tǒng)調(diào)用,主要使用 Nginx 服務(wù)器的 事件驅(qū)動(dòng)模型 來(lái)實(shí)現(xiàn)。
?
?
?
如上圖所示,Nginx 的 事件驅(qū)動(dòng)模型 由 事件收集器、事件發(fā)送器 和 事件處理器 三部分基本單元組成。
-
事件收集器:負(fù)責(zé)收集 worker 進(jìn)程的各種 IO 請(qǐng)求;
-
事件發(fā)送器:負(fù)責(zé)將 IO 事件發(fā)送到 事件處理器;
-
事件處理器:負(fù)責(zé)各種事件的 響應(yīng)工作。
事件發(fā)送器 將每個(gè)請(qǐng)求放入一個(gè) 待處理事件列表,使用非阻塞 I/O 方式調(diào)用 事件處理器 來(lái)處理該請(qǐng)求。其處理方式稱為 “多路 IO 復(fù)用方法”,常見(jiàn)的包括以下三種:select 模型、poll 模型、epoll 模型。
5. Nginx進(jìn)程處理模型
Nginx 服務(wù)器使用 master/worker 多進(jìn)程模式。多線程啟動(dòng)和執(zhí)行的流程如下:
主程序 Master process 啟動(dòng)后,通過(guò)一個(gè) for 循環(huán)來(lái) 接收 和 處理外部信號(hào);
主進(jìn)程 通過(guò) fork() 函數(shù)產(chǎn)生 worker 子進(jìn)程,每個(gè) 子進(jìn)程 執(zhí)行一個(gè) for 循環(huán)來(lái)實(shí)現(xiàn) Nginx 服務(wù)器 對(duì)事件的接收 和 處理。
一般推薦 worker 進(jìn)程數(shù) 與 CPU 內(nèi)核數(shù) 一致,這樣一來(lái)不存在 大量的子進(jìn)程 生成和管理任務(wù),避免了進(jìn)程之間 競(jìng)爭(zhēng) CPU 資源 和 進(jìn)程切換 的開(kāi)銷。而且 Nginx 為了更好的利用 多核特性,提供了 CPU 親緣性 的綁定選項(xiàng),我們可以將某 一個(gè)進(jìn)程綁定在某一個(gè)核 上,這樣就不會(huì)因?yàn)?進(jìn)程的切換 帶來(lái) Cache 的失效。
對(duì)于每個(gè)請(qǐng)求,有且只有一個(gè) 工作進(jìn)程 對(duì)其處理。首先,每個(gè) worker 進(jìn)程都是從 master 進(jìn)程 fork 過(guò)來(lái)。在 master 進(jìn)程里面,先建立好需要 listen 的 socket(listenfd) 之后,然后再 fork 出多個(gè) worker 進(jìn)程。
所有 worker 進(jìn)程的 listenfd 會(huì)在 新連接 到來(lái)時(shí)變得 可讀,為保證只有一個(gè)進(jìn)程處理該連接,所有 worker 進(jìn)程在注冊(cè) listenfd 讀事件 前 搶占 accept_mutex,搶到 互斥鎖 的那個(gè)進(jìn)程 注冊(cè) listenfd 讀事件,在 讀事件 里調(diào)用 accept 接受該連接。
當(dāng)一個(gè) worker 進(jìn)程在 accept 這個(gè)連接之后,就開(kāi)始 讀取請(qǐng)求,解析請(qǐng)求,處理請(qǐng)求,產(chǎn)生數(shù)據(jù)后,再 返回給客戶端,最后才 斷開(kāi)連接,這樣一個(gè)完整的請(qǐng)求就是這樣的了。我們可以看到,一個(gè)請(qǐng)求,完全由 worker 進(jìn)程來(lái)處理,而且只在一個(gè) worker 進(jìn)程中處理。
?
?
?
在 Nginx 服務(wù)器的運(yùn)行過(guò)程中,主進(jìn)程 和 工作進(jìn)程 需要進(jìn)程交互。交互依賴于 Socket 實(shí)現(xiàn)的 管道 來(lái)實(shí)現(xiàn)。
5.1. 主進(jìn)程與工作進(jìn)程交互
這條管道與普通的管道不同,它是由 主進(jìn)程 指向 工作進(jìn)程 的 單向管道,包含主進(jìn)程向工作進(jìn)程發(fā)出的 指令,工作進(jìn)程 ID 等;同時(shí) 主進(jìn)程 與外界通過(guò) 信號(hào)通信;每個(gè) 子進(jìn)程 具備 接收信號(hào),并處理相應(yīng)的事件的能力。
5.2. 工作進(jìn)程與工作進(jìn)程交互
這種交互是和 主進(jìn)程-工作進(jìn)程 交互是基本一致的,但是會(huì)通過(guò) 主進(jìn)程 間接完成。工作進(jìn)程 之間是 相互隔離 的,所以當(dāng)工作進(jìn)程 W1 需要向工作進(jìn)程 W2 發(fā)指令時(shí),首先找到 W2 的 進(jìn)程 ID,然后將正確的指令寫(xiě)入指向 W2 的 通道。W2 收到信號(hào)采取相應(yīng)的措施。
小結(jié)
通過(guò)這篇文章,我們對(duì) Nginx 服務(wù)器的 整體架構(gòu) 有了一個(gè)整體的認(rèn)識(shí)。包括其 模塊化的設(shè)計(jì)、多進(jìn)程 和 異步非阻塞 的請(qǐng)求處理方式、事件驅(qū)動(dòng)模型 等。通過(guò)這些理論知識(shí),才能更好地領(lǐng)悟 Nginx 的設(shè)計(jì)思想。對(duì)于我們學(xué)習(xí) Nginx 來(lái)說(shuō)有很大的幫助。
作者:零壹技術(shù)棧
鏈接:https://juejin.im/post/5b4bdb54e51d45191e0cd774
來(lái)源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
來(lái)源:https://juejin.im/post/5b4bdb54e51d45191e0cd774
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的浅谈Nginx服务器的内部核心架构设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 就业协议中的入伍包含军队文职录用吗
- 下一篇: mysql进阶(十五) mysql批量删