從 Nginx 優(yōu)秀的核心架構(gòu)設(shè)計(jì)昂勉,揭秘其為何能支持高并發(fā)?

目錄:1. Nginx的整體架構(gòu)2. Nginx的模塊化設(shè)計(jì)3. Nginx的請(qǐng)求方式處理4. Nginx事件驅(qū)動(dòng)模型5. Nginx進(jìn)程處理模型

寫在前面

Nginx 是一個(gè) 免費(fèi)的扫腺,開源的岗照,高性能的 HTTP 服務(wù)器和反向代理。以其高性能,穩(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ò)讀寫 咙俩、 存儲(chǔ)讀寫、 內(nèi)容傳輸 湿故、 外出過濾 阿趁,以及將請(qǐng)求發(fā)往上游服務(wù)器等。

而其代碼的模塊化設(shè)計(jì) 坛猪,也使得我們可以根據(jù)需要對(duì) 功能模塊 進(jìn)行適當(dāng)?shù)?選擇 和 修改 歌焦,編譯成具有 特定功能的服務(wù)器。

1.4. 事件驅(qū)動(dòng)模型

基于 異步及非阻塞的事件驅(qū)動(dòng)模型 砚哆,可以說是 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ì)搜立,可以說是 Nginx 深入骨髓的設(shè)計(jì)以躯,無論是對(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)用全庸,完成開發(fā)者自定義功能,比如: Json 支持壶笼、 Lua 支持等神僵。

3. Nginx的請(qǐng)求方式處理

Nginx 是一個(gè) 高性能 的 Web 服務(wù)器,能夠同時(shí)處理大量的并發(fā)請(qǐng)求 拌消。它結(jié)合多進(jìn)程機(jī)制和 異步機(jī)制 挑豌,異步機(jī)制使用的是 異步非阻塞方式 ,接下來就給大家介紹一下 Nginx 的 多線程機(jī)制 和 異步非阻塞機(jī)制 墩崩。

3.1. 多進(jìn)程機(jī)制

服務(wù)器每當(dāng)收到一個(gè)客戶端時(shí)氓英,就有 服務(wù)器主進(jìn)程 ( master process )生成一個(gè) 子進(jìn)程( worker process )出來和客戶端建立連接進(jìn)行交互,直到連接斷開鹦筹,該子進(jìn)程就結(jié)束了铝阐。

使用 進(jìn)程 的好處是 各個(gè)進(jìn)程之間相互獨(dú)立 , 不需要加鎖 铐拐,減少了使用鎖對(duì)性能造成影響徘键,同時(shí)降低編程的復(fù)雜度,降低開發(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)生一定的開銷谓媒。當(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)求 (即為非阻塞 ),而客戶端在此期間也無需等待響應(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)模型來實(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)用 事件處理器來處理該請(qǐng)求陋葡。

其處理方式稱為 “多路 IO 復(fù)用方法” 腐缤,常見的包括以下三種: select 模型、 poll模型惜索、 epoll 模型巾兆。

5. Nginx進(jìn)程處理模型

Nginx 服務(wù)器使用master/worker多進(jìn)程模式角塑,多線程啟動(dòng)和執(zhí)行的流程如下:

主程序Master process啟動(dòng)后溜宽,通過一個(gè) for 循環(huán)來接收和處理外部信號(hào)

主進(jìn)程通過 fork() 函數(shù)產(chǎn)生 worker 子進(jìn)程 适揉,每個(gè) 子進(jìn)程 執(zhí)行一個(gè) for 循環(huán)來實(shí)現(xiàn) Nginx 服務(wù)器 對(duì)事件的接收 和 處理

一般推薦 worker 進(jìn)程數(shù) 與 CPU 內(nèi)核數(shù) 一致,這樣一來不存在 大量的子進(jìn)程 生成和管理任務(wù)炼邀,避免了進(jìn)程之間 競(jìng)爭(zhēng) CPU 資源 和 進(jìn)程切換 的開銷拭宁。

而且 Nginx 為了更好的利用 多核特性 杰标,提供了 CPU 親緣性 的綁定選項(xiàng)彩匕,我們可以將某 一個(gè)進(jìn)程綁定在某一個(gè)核上驼仪,這樣就不會(huì)因?yàn)?進(jìn)程的切換 帶來 Cache 的失效袜漩。

對(duì)于每個(gè)請(qǐng)求宙攻,有且只有一個(gè) 工作進(jìn)程 對(duì)其處理座掘。首先雹顺,每個(gè) worker 進(jìn)程都是從 master進(jìn)程 fork 過來嬉愧。在 master 進(jìn)程里面,先建立好需要 listen 的 socket(listenfd) 之后没酣,然后再 fork 出多個(gè) worker 進(jìn)程卵迂。

所有 worker 進(jìn)程的 listenfd 會(huì)在 新連接 到來時(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è)連接之后庆揩,就開始讀取請(qǐng)求 , 解析請(qǐng)求 虏辫, 處理請(qǐng)求砌庄,產(chǎn)生數(shù)據(jù)后,再返回給客戶端 ,最后才斷開連接 验辞,一個(gè)完整的請(qǐng)求就是這樣跌造。

我們可以看到,一個(gè)請(qǐng)求陵珍,完全由 worker 進(jìn)程來處理违施,而且只在一個(gè) worker 進(jìn)程中處理磕蒲。

如下圖所示:

在 Nginx 服務(wù)器的運(yùn)行過程中兔院, 主進(jìn)程 和 工作進(jìn)程 需要進(jìn)程交互站削。交互依賴于 Socket 實(shí)現(xiàn)的管道來實(shí)現(xiàn)。

5.1. 主進(jìn)程與工作進(jìn)程交互

這條管道與普通的管道不同十偶,它是由 主進(jìn)程 指向 工作進(jìn)程 的單向管道 扯键,包含主進(jìn)程向工作進(jìn)程發(fā)出的指令工珊肃,作進(jìn)程 ID 等伦乔。同時(shí)主進(jìn)程與外界通過信號(hào)通信 ;每個(gè)子進(jìn)程具備接收信號(hào) 爱只,并處理相應(yīng)的事件的能力恬试。

5.2. 工作進(jìn)程與工作進(jìn)程交互

這種交互和 主進(jìn)程-工作進(jìn)程 交互基本一致,但是會(huì)通過主進(jìn)程間接完成哑舒,工作進(jìn)程之間是相互隔離的幻馁。

所以當(dāng)工作進(jìn)程 W1 需要向工作進(jìn)程 W2 發(fā)指令時(shí)仗嗦,首先找到 W2 的 進(jìn)程ID ,然后將正確的指令寫入指向 W2 的 通道火邓,W2 收到信號(hào)采取相應(yīng)的措施贡翘。

小結(jié)

通過這篇文章砰逻,我們對(duì) Nginx 服務(wù)器的 整體架構(gòu) 有了一個(gè)整體的認(rèn)識(shí)。包括其 模塊化的設(shè)計(jì)踊东、 多進(jìn)程 和 異步非阻塞 的請(qǐng)求處理方式刚操、 事件驅(qū)動(dòng)模型 等菊霜。

通過這些理論知識(shí)鉴逞,才能更好地領(lǐng)悟 Nginx 的設(shè)計(jì)思想。對(duì)于我們學(xué)習(xí) Nginx 來說有很大的幫助液南。

最后

分享一份特別好的Nginx學(xué)習(xí)資料【Nginx實(shí)戰(zhàn).pdf】滑凉,有需要的老鐵加入群(Java高級(jí)架構(gòu)進(jìn)階)736-351-661即可免費(fèi)獲取到畅姊!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末朱嘴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子级乍,更是在濱河造成了極大的恐慌,老刑警劉巖甚淡,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異撵割,居然都是意外死亡辙芍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吃衅,“玉大人徘层,你說我怎么就攤上這事趣效∩缴希” “怎么了佩憾?”我有些...
    開封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵楞黄,是天一觀的道長(zhǎng)渣聚。 經(jīng)常有香客問我庐舟,道長(zhǎng)伯襟,這世上最難降的妖魔是什么雷蹂? 我笑而不...
    開封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮党巾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘齿拂。我一直安慰自己达舒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開白布叹侄。 她就那樣靜靜地躺著巩搏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪趾代。 梳的紋絲不亂的頭發(fā)上贯底,一...
    開封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音撒强,去河邊找鬼禽捆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛飘哨,可吹牛的內(nèi)容都是我干的胚想。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼芽隆,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吨掌,我...
    開封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤秋茫,失蹤者是張志新(化名)和其女友劉穎乘瓤,沒想到半個(gè)月后抬吟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聪建,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡揍魂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年庄蹋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秉扑。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡秦躯,死狀恐怖哨免,靈堂內(nèi)的尸體忽然破棺而出载荔,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布踪危,位于F島的核電站,受9級(jí)特大地震影響官疲,放射性物質(zhì)發(fā)生泄漏溢吻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一贱枣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧昵仅,春花似錦、人聲如沸梯投。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)窍荧。三九已至咕痛,卻和暖如春腔丧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工搁嗓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留路翻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像狰闪,于是被迫代替她去往敵國(guó)和親幔欧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子礁蔗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容