IT運(yùn)維架構(gòu) | Nginx 架構(gòu)詳解
2020-03-28 20:08 作者:艾銻無(wú)限 瀏覽量:
與眾不同的服務(wù)是因?yàn)橛行?/strong>
所有艾銻人可能都知道艾銻無(wú)限為客戶(hù)提供三種與客戶(hù)接觸的方式,一種是產(chǎn)品,一種是技術(shù),還有一種是服務(wù),那這三種所謂的方式構(gòu)建起一個(gè)三角形,這種穩(wěn)固的體系,看起來(lái)還不錯(cuò),但我們細(xì)細(xì)思考卻發(fā)現(xiàn)很多企業(yè)也都提供這三種方式與客戶(hù)建立一個(gè)長(zhǎng)久的關(guān)系。
那艾銻無(wú)限到底與這些企業(yè)有什么區(qū)別呢?有什么明顯的區(qū)別,讓客戶(hù)和其他人一看這種服務(wù)就明白是艾銻無(wú)限的服務(wù),這個(gè)世界上獨(dú)一無(wú)二的服務(wù)呢,大家都看過(guò)3D電影吧,無(wú)論后來(lái)的技術(shù)提升或其他人如何模仿,如何超越,大家首先可能想到的3D電影的代表作是《阿凡達(dá)》,是的這就是獨(dú)一無(wú)二,那如何讓我們的三種與客戶(hù)建立聯(lián)系的方式也能變的立體呢,我們來(lái)看怎樣把這三種方式賦予生命,讓他們與眾不同.
大家可能已發(fā)現(xiàn)原來(lái)“艾銻服務(wù)心”讓我們的服務(wù)變的立體,開(kāi)始有了美感,開(kāi)始賦予了新的生命,而不是之前人們認(rèn)為的那種“無(wú)聊”,沒(méi)有生趣的服務(wù),這是一種全新的與客戶(hù)建立聯(lián)系的方式,與客戶(hù)產(chǎn)生互動(dòng)的方式,這是生命與生命的互動(dòng),這是靈魂與靈魂間的碰撞,就像我們的每一顆蒲公英種子一樣讓每一次與人的接觸都賦予了生命,而不是人與機(jī)器的單調(diào)互動(dòng),更不是那種看起來(lái)死氣沉沉的三角形。我們用我們的愛(ài),付出,喜悅轉(zhuǎn)化出我們的誠(chéng)心,細(xì)心,貼心的彼此體驗(yàn),讓更多的三面體不斷去聚合,形成一顆璀璨的鉆石。
這就這個(gè)世界上與眾不同的艾銻服務(wù),這就是艾銻無(wú)限的現(xiàn)成,這更是艾銻無(wú)限的未來(lái)。
Nginx 服務(wù)器是一個(gè)高性能的 Web 和反向代理服務(wù)器。Nginx 在激烈的 Web 服務(wù)器競(jìng)爭(zhēng)中依舊保持良好的發(fā)展勢(shì)頭,一度成為 Web 服務(wù)器市場(chǎng)的后期之秀,這一切跟 Nginx 的架構(gòu)設(shè)計(jì)是分不開(kāi)的。
Nginx 模塊化設(shè)計(jì)
高度模塊化的設(shè)計(jì)是 Nginx 的架構(gòu)基礎(chǔ)。Nginx 服務(wù)器被分解為多個(gè)模塊,每個(gè)模塊就是一個(gè)功能模塊,只負(fù)責(zé)自身的功能,模塊之間嚴(yán)格遵循“高內(nèi)聚,低耦合”的原則。
核心模塊
核心模塊是 Nginx 服務(wù)器正常運(yùn)行必不可少的模塊,提供錯(cuò)誤日志記錄、配置文件解析、事件驅(qū)動(dòng)機(jī)制、進(jìn)程管理等核心功能。
標(biāo)準(zhǔn) HTTP 模塊
標(biāo)準(zhǔn) HTTP 模塊提供 HTTP 協(xié)議解析相關(guān)的功能,如:端口配置、網(wǎng)頁(yè)編碼設(shè)置、HTTP 響應(yīng)頭設(shè)置等。
可選 HTTP 模塊
可選 HTTP 模塊主要用于擴(kuò)展標(biāo)準(zhǔn)的 HTTP 功能,讓 Nginx 能處理一些特殊的服務(wù),如:Flash 多媒體傳輸、解析 GeoIP 請(qǐng)求、SSL 支持等。
郵件服務(wù)模塊
郵件服務(wù)模塊主要用于支持 Nginx 的郵件服務(wù),包括對(duì) POP3 協(xié)議、IMAP 協(xié)議和 SMTP 協(xié)議的支持。
第三方模塊
第三方模塊是為了擴(kuò)展 Nginx 服務(wù)器應(yīng)用,完成開(kāi)發(fā)者自定義功能,如:Json 支持、Lua 支持等。
Nginx 請(qǐng)求處理方式
Nginx 是一個(gè)高性能的 Web 服務(wù)器,能夠同時(shí)處理大量的并發(fā)請(qǐng)求。它結(jié)合多進(jìn)程機(jī)制和異步機(jī)制,異步機(jī)制使用的是異步非阻塞方式,接下來(lái)就給大家介紹一下 Nginx 的多線(xiàn)程機(jī)制和異步非阻塞機(jī)制。
多進(jìn)程
服務(wù)器每當(dāng)收到一個(gè)客戶(hù)端時(shí)。就有服務(wù)器主進(jìn)程(master process)生成一個(gè)子進(jìn)程(worker process)出來(lái)和客戶(hù)端建立連接進(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ù)部中斷,將風(fēng)險(xiǎn)降到最低。
缺點(diǎn)是操作系統(tǒng)生成一個(gè)子進(jìn)程需要進(jìn)行內(nèi)存復(fù)制等操作,在資源和時(shí)間上會(huì)產(chǎn)生一定的開(kāi)銷(xiāo);當(dāng)有大量請(qǐng)求時(shí),會(huì)導(dǎo)致系統(tǒng)性能下降。
異步非阻塞
每個(gè)工作進(jìn)程使用異步非阻塞方式,可以處理多個(gè)客戶(hù)端請(qǐng)求。當(dāng)某個(gè)工作進(jìn)程接收到客戶(hù)端的請(qǐng)求以后,調(diào)用 IO 進(jìn)行處理,如果不能立即得到結(jié)果,就去處理其他的請(qǐng)求(即為非阻塞);而客戶(hù)端在此期間也無(wú)需等待響應(yīng),可以去處理其他事情(即為異步);當(dāng) IO 返回時(shí),就會(huì)通知此工作進(jìn)程;該進(jìn)程得到通知,暫時(shí)掛起當(dāng)前處理的事務(wù)去響應(yīng)客戶(hù)端請(qǐng)求。
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)求。其處理方式稱(chēng)為“多路 IO 復(fù)用方法”,常見(jiàn)的包括以下三種:select 模型、poll 模型、epoll 模型。
針對(duì)上面的技術(shù)我特意整理了一下,有很多技術(shù)不是靠幾句話(huà)能講清楚,所以干脆找朋友錄制了一些視頻,很多問(wèn)題其實(shí)答案很簡(jiǎn)單,但是背后的思考和邏輯不簡(jiǎn)單,要做到知其然還要知其所以然。
Nginx 設(shè)計(jì)架構(gòu)
Nginx 服務(wù)器使用 master/worker 多進(jìn)程模式。多線(xiàn)程啟動(dòng)和執(zhí)行的流程如下:主程序 Master process 啟動(dòng)后,通過(guò)一個(gè) for 循環(huán)來(lái)接收和處理外部信號(hào);主進(jìn)程通過(guò) fork() 函數(shù)產(chǎn)生子進(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)銷(xiāo)。而且 Nginx 為了更好的利用多核特性,提供了 cpu 親緣性的綁定選項(xiàng),我們可以將某一個(gè)進(jìn)程綁定在某一個(gè)核上,這樣就不會(huì)因?yàn)檫M(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ù)后,再返回給客戶(hù)端,最后才斷開(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)程交互。交互依賴(lài)于 Socket 實(shí)現(xiàn)的管道來(lái)實(shí)現(xiàn)。
Master-Worker 交互
這條管道與普通的管道不同,它是由主進(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)的事件的能力。
worker-worker 交互
這種交互是和 Master-Worker 交互是基本一致的,但是會(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í),對(duì)于我們以后學(xué)習(xí) Nginx 的源碼有很大的幫助;也推薦大家多看看 Nginx 的源碼,才能更好地領(lǐng)悟 Nginx 的設(shè)計(jì)思想。