www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]“Nginx(enginex)是一個高性能的HTTP和反向代理Web服務(wù)器,同時也提供了IMAP/POP3/SMTP服務(wù)。圖片來自PexelsNginx以高性能和高可用性備受廣大程序員的青睞,今天我們會從Nginx的整體架構(gòu)入手,介紹Nginx進程結(jié)構(gòu),進程之間的關(guān)系以及如何對進...


Nginx(engine x)是一個高性能的 HTTP 和反向代理 Web 服務(wù)器,同時也提供了 IMAP/POP3/SMTP 服務(wù)。



圖片來自 Pexels

Nginx 以高性能和高可用性備受廣大程序員的青睞,今天我們會從 Nginx 的整體架構(gòu)入手,介紹 Nginx 進程結(jié)構(gòu),進程之間的關(guān)系以及如何對進程進行控制和管理。



今天大家會學(xué)到如下內(nèi)容:


  • Nginx 總體架構(gòu)


  • Nginx 進程定義


  • Nginx 啟動過程


  • Master 啟動過程


  • 進程之間的信號發(fā)送方式


  • 進程協(xié)助處理網(wǎng)絡(luò)請求



Nginx 總體架構(gòu)



對于傳統(tǒng)的 HTTP 和反向代理服務(wù)器而言,在處理并發(fā)請求的時候會使用單進程或線程的模式處理,同時會止網(wǎng)絡(luò)或輸入/輸出操作。



這種方式會消耗大量的內(nèi)存和 CPU 資源。因為每產(chǎn)生一個單獨的進程或線程需要準(zhǔn)備一套新的運行時環(huán)境,包括分配堆和堆棧內(nèi)存,以及創(chuàng)建新的執(zhí)行上下文。



可以想象在處理多請求時會生成對應(yīng)數(shù)目的線程或進程,導(dǎo)致由于線程在不斷上下文切換上耗費大量資源。



由于上面的原因,Nginx 在設(shè)計之初就使用了模塊化、事件驅(qū)動、異步處理,非阻塞的架構(gòu)。


圖 1:Nginx 總體架構(gòu)



讓我們通過一張圖來了解 Nginx 的總結(jié)架構(gòu),如圖 1 所示:



Nginx 啟動時,并不會馬上處理網(wǎng)絡(luò)請求,負(fù)責(zé)調(diào)度工作進程。包括 Load configuration(加載配置),Launch workers(啟動工作進程)以及 Non-stop upgrade(平滑升級)。



因此在 Nginx 啟動以后,在操作系統(tǒng)中會看到 Master 和 Worker 兩類進程。在圖上方的 Master 進程負(fù)責(zé)加載分析配置文件、啟動/管理 Worker 進程以及平滑升級。



一個 Master 進程可以管理多個 Worker 進程,而 Worker 進程負(fù)責(zé)處理并響應(yīng)用戶請求,也就是來自圖左邊的 HTTP/HTTPS 請求。



由于網(wǎng)絡(luò)請求屬于 IO 請求,為了應(yīng)對高并發(fā) Nginx 采取了 kevent/epoll/ select 模式的多路復(fù)用技術(shù)。由于采取了這種技術(shù)每個 Worker 進程都可以同時處理數(shù)以千計的網(wǎng)絡(luò)請求。



為了處理網(wǎng)絡(luò)請求在 Worker 中會包含模塊,分為核心模塊和功能性模塊。



核心模塊負(fù)責(zé)維持一個運行循環(huán)(run-loop),執(zhí)行網(wǎng)絡(luò)請求處理的不同階段的模塊功能,如網(wǎng)絡(luò)讀寫、存儲讀寫、內(nèi)容傳輸、外出過濾,以及將請求發(fā)往上游服務(wù)器等。



而圍繞著核心模塊會有一些功能模塊,就是實現(xiàn)具體的請求處理功能的。例如有處理 http 請求的 ht_core 模塊,有實現(xiàn)負(fù)載均衡的 ht_upstream 模塊,以及實現(xiàn) FastCGI 的 ht_fastcgi 模塊。



這些模塊會負(fù)責(zé)與后端的服務(wù)器進行交互,完成用戶請求,同時可以根據(jù)需要的功能自由加載模塊,甚至可以擴展第三方的模塊。



Worker 進程可以和本地磁盤進行數(shù)據(jù)通信,支持 Advanced I/O(高級I/O)、sendfile 機制、AIO 機制、mmap 等機制等。



通過上面的介紹發(fā)現(xiàn) Nginx 不會為每個連接生成一個進程或線程,而是通過 Worker 進程使用多路復(fù)用的方式處理多個請求。



這里會使用到共享監(jiān)聽套接字的方式接受新請求,并在每個 Worker 內(nèi)執(zhí)行高效的運行循環(huán),從而達(dá)到每個 Worker 處理成千上萬的連接。



Work 啟動后將創(chuàng)建一組偵聽套接字,并且在處理 HTTP 請求和響應(yīng)過程中不斷接受,讀取和寫入套接字信息。



運行循環(huán)(run-loop)包括全面的內(nèi)部調(diào)用,并且在很大程度上依賴異步任務(wù)處理。



通過模塊化,事件通知,回調(diào)函數(shù)和定時器來支撐異步操作的實現(xiàn)。其目的是為了實現(xiàn)高并發(fā)請求下的不阻塞(盡可能不阻賽)。



基于上面的機制,Nginx 通過檢查網(wǎng)絡(luò)和存儲的狀態(tài)并初始化新連接,將其添加到運行循環(huán)中,并異步處理直到其完成,處理完畢的連接會被重新分配并從運行循環(huán)中刪除。因此 Nginx 可以在極端工作負(fù)載下實現(xiàn)較低的CPU使用率。



另外,由于 Work 會在磁盤上進行寫入操作,為了避免磁盤 I/O 上的阻塞請求,特別是磁盤滿的情況。



可以設(shè)置機制和配置文件指令來減輕此類磁盤 I/O 阻塞情況的發(fā)生。例如使用 sendfile 和 AIO 組合選項提升磁盤性能。



Nginx 進程定義



從架構(gòu)介紹我們知道 Nginx 是由不同的進程組成的,這些進程各司其職用來處理高并發(fā)下的網(wǎng)絡(luò)請求,接下來就看看他們的定義和如何工作的。



上面介紹了 Nginx 的總體架構(gòu),其中重點提到了 Master 進程和 Worker 進程,其實還有另外兩個進程在架構(gòu)中也起到了重要的作用。


圖 2:Nginx 的四類進程
這里我們一起通過圖 2 來認(rèn)識他們:


  • Master 進程:它作為父進程會在 Nginx 初始化的時候生成并啟動,其他的進程都是它子進程,Master 進程對其他進行進行創(chuàng)建和管理。


  • Worker 進程:是 Master 的子進程負(fù)責(zé)處理網(wǎng)絡(luò)請求。這里需要說明一下 Nginx 為什么采用了多進程而不是多線程的結(jié)構(gòu),其原因是為了保證高可用性,進程不像線程那樣共享地址空間,也避免了當(dāng)一個線程中的第三方模塊出錯引而影響其他其他線程的情況發(fā)生。


  • Cache Manager 和 Cache Loader 進程:Cache Loader 負(fù)責(zé)緩存載入,Cache Manager 負(fù)責(zé)緩存管理,每一個請求所使用的緩存還是由 Worker 來決定的,而進程間通信都是通過共享內(nèi)存來實現(xiàn)的。



從上圖大家一定注意到了只有 Worker 進程是多個,這是因為 Nginx 采用了事件驅(qū)動的模型。



為了提高處理請求的效率每個 Worker 進程會找那個一個 CPU內(nèi)核,提高 CPU 的緩存命中率,將某個 Worker 進程與一個 CPU 核綁定在一起。



需要說明的是,我們需要根據(jù)具體的應(yīng)用場景來定義 Worker 進程的數(shù)量:


  • CPU 密集型請求,例如,處理大量 TCP/IP,執(zhí)行 SSL 或壓縮,需要 Worker 數(shù)與 CPU 內(nèi)核數(shù)量相匹配。


  • IO 密集型請求,Worker 數(shù)需要是 CPU 內(nèi)核數(shù)量的一到兩倍。



上面提到了 Master 通過控制多個 Worker 進程來處理網(wǎng)絡(luò)請求,對于 Worker 的獨立進程來說使用資源的時候不需要考慮不需要加鎖的問題,節(jié)省了因為加鎖帶來的系統(tǒng)開銷。同時多進程的設(shè)計讓進程之間不會互相影響。



當(dāng)一個進程退出后,其它進程還在工作,Nginx 所提供的網(wǎng)絡(luò)請求服務(wù)不會因為其中一個進程的退出而中斷,Master 進程一旦發(fā)現(xiàn)有 Worker 進程退出會啟動新的 Worker 進程。



這里我們會發(fā)現(xiàn) Master 進程為了控制 Worker 需要對其進行通信,同時 Worker 進程也需要與 Master 進程交換信息。



Nginx 啟動過程



談到了 Master 進程如此的重要,那么一起來看看 Nginx 進程的啟動過程。圖 3:Nginx 啟動 Master 進程



如圖 3 所示,在 Nginx 啟動的時候會根據(jù)配置文件進行解析和初始化的工作,同時會從主進程中 fork 出一個 Master 進程作為自己的子進程,也就是啟動 Master 進程,此時 Master 進程就誕生了。



Nginx 的主進程在 fork 出 Master 進程以后就退出了。然后 Master 進程會 fork 并啟動 Worker 進程,以及 Cache Manager 、Cache Loader 進程,接著 Master 進程會進入主循環(huán)。



需要注意的是,這里使用的 fork 會復(fù)制一個和當(dāng)前啟動進程具有相同代碼段、數(shù)據(jù)段、堆和棧、fd 等信息的子進程。



也就是說我們說的四類進程都是通過 Nginx 啟動進程復(fù)制出來的子進程。



Master 啟動過程



接著上面的流程 Master 進程被 fork 之后,會執(zhí)行 ngx_master_process_cycle 函數(shù)。


圖 4:Master 進程執(zhí)行 ngx_master_process_cycle 函數(shù)



如圖 4 所示,這個函數(shù)主要進行如下操作:


  • 設(shè)置進程的初始信號掩碼,屏蔽相關(guān)信號。


  • Master 進程 fork 出 Worker 、Cache Manager 以及 Cache Loader 等子進程。


  • 進入主循環(huán),通過 sigsuspend 系統(tǒng)調(diào)用,等待著信號的到來。


  • 一旦信號到來,會進入信號處理程序 ngx_signal_handler。


  • 信號處理程序執(zhí)行之后,程序執(zhí)行流程會判斷各種狀態(tài)位,來執(zhí)行不同的操作。



上面的流程中提到了幾個概念,這里對其進行說明,以便我們更好的理解 Master 進程的執(zhí)行過程。



①信號:用來完成進程中信息傳遞的媒介。Master 進程的主循環(huán)里面,一直通過等待各種信號事件,來處理不同的指令。



這個信號可以傳遞給 Master 進程,也可以從 Master 進程傳遞給其他的進程。



信號分為標(biāo)準(zhǔn)信號和實時信號,標(biāo)準(zhǔn)信號是從 1-31,實時信號是從 32-64。例如:INT、QUIT、KILL 就是標(biāo)準(zhǔn)信號。Master 進程監(jiān)聽的信號也是標(biāo)準(zhǔn)信號。



標(biāo)準(zhǔn)信號和實時信號的區(qū)別是:標(biāo)準(zhǔn)信號,是基于位的標(biāo)記,假設(shè)在阻塞等待的時候,多個相同的信號到來,最終解除阻塞時,只會傳遞一次信號,無法統(tǒng)計等待期間信號的計數(shù)。



而實時信號是通過隊列來實現(xiàn),在阻塞等待的時候,多個相同的實時信號會存放到隊列中。一旦解除阻塞的時候,會將隊列中的信號都進行傳遞,結(jié)果會收到多次信號。



②信號處理器:信號處理器是指當(dāng)捕獲指定信號時(傳遞給進程)時將會調(diào)用的一個函數(shù),它存在與進程中,它可以隨時打斷進程的主程序流程。



③發(fā)送信號:發(fā)送信號的操作可以使用 kill 這個 shell 命令完成。比如 kill -9 pid,就是發(fā)送 KILL 信號。



kill -INT pid 就是發(fā)送 INT 信號。與 shell 命令類似,可以使用 kill 系統(tǒng)調(diào)用來向進程發(fā)送信號。



④信號掩碼:用來控制信號阻賽的編碼方式。每個進程都有一個信號掩碼(signal mask),也稱為信號屏蔽字,它規(guī)定了當(dāng)前要屏蔽或要阻塞遞送到該進程的信號集。



對于每種可能的信號,該掩碼中都有一位與之對應(yīng)。對于某種信號,若其對應(yīng)位(bit)已設(shè)置,則它當(dāng)前是被阻塞的。



簡單地說,信號掩碼是一個“位圖”,其中每一位都對應(yīng)著一種信號。如果位圖中的某一位為 1,就表示在執(zhí)行當(dāng)前信號集的處理程序期間相應(yīng)的信號暫時被“屏蔽”或“阻塞”,使得在執(zhí)行的過程中不會嵌套地響應(yīng)那個信號。



說白了就是使用信號編碼來阻賽信號,告訴其他發(fā)送信號的進程說:“我在忙著處理事情,你先等等,等會我再處理你的信號。”



進程之間的信號發(fā)送方式



有了上面的基礎(chǔ)以后再回頭看看 Nginx 中進程中是如何進行信息交互的,以及 Master 是如何通過信號與 Worker 進行溝通的。圖 5:Master 與 Worker 通信



從圖 5 中可以看出,Master 可以接受 TERM,INT、QUIT、HUP、USR1、USR2、WINCH 這些信號,這些信號的含義會在后面提供一張表給大家解釋。



同時 Master 進程也可以給Worker進程傳遞信號,于是 Worker 進程可以接收以下信號:TERM,INT、QUIT、HUP、USR1、WINCH。之后 Worker 再去響應(yīng) Client 的請求。



這里先將信號的對應(yīng)的命令和含義通過表格的方式列出來,再來對其進行講解。


從表格上面看,每個信號都有特定的含義。比如 QUIT 信號表示優(yōu)雅地關(guān)閉服務(wù),并且對應(yīng) quit 命令。



這里的 quit 命令指的是可以通過命令行的方式對 Master 進程下命令,從而達(dá)到發(fā)送信號的效果,當(dāng)然 Master 接受到命令以后會轉(zhuǎn)化為信號發(fā)送給對應(yīng)的 Worker 達(dá)到關(guān)閉服務(wù)的效果。



需要說明的是,Worker 是不會接受命令的,而是通過 Worker 接受命令來統(tǒng)一管理所有 Worker 的行為。



進程協(xié)助處理網(wǎng)絡(luò)請求



知道 Master 與 Worker 之間如何通信之后再來看看它們是如何合作完成客戶端請求的。圖 6:Client 請求流程



如圖 6 所示,這里描繪了 Master 創(chuàng)建 Listen 以及 fork 出 Worker 的過程,以及客戶端請求和 Worker 響應(yīng)請求的過程。



先從最上面開始看,順著從上至下紅色的箭頭看,Master 進程創(chuàng)建以后會通過 socket 方法創(chuàng)建 socket 的 IO 通道。



接著執(zhí)行 bind 方法將其與監(jiān)聽器 listen 進行綁定,然后通過 fork 方法 fork 出多個 Worker 進程(綠色虛線)。



在每個 Worker 進程中的 accept 方法就監(jiān)聽 socket 請求了,一旦 listen 監(jiān)聽到 socket 請求 Worker 進程就可以通過 accept 接受到。



再看最下面的 client 模塊,當(dāng) client 通過 connect 方法與 Nginx 發(fā)生連接時,所有擁有 accept 方法的 Worker 進程都會接受到來自 listen 的通知,但是只有一個 Worker 進程能夠成功 accept 到,其他的進程則會失敗。



這里 Nginx 提供了一把共享鎖 accept_mutex 來保證同一時刻只有一個 Worker 進程在 accept 連接,從而解決驚群問題。



當(dāng) Worker 進程 accept 到 socket 請求以后,client 會通過 send 方法發(fā)送請求(綠色虛線)給 Worker。



而 Worker 使用 recv 方法接受請求你,同時通過 parse(解析)、process(處理)、generate(生成響應(yīng))幾個步驟將返回的響應(yīng)通過 send 方法傳送給 client,而 client 會使用 recv 方法接受響應(yīng)。



最后 Worker 調(diào)用 close 方法斷開和 client 的連接。



總結(jié)



本文從 Nginx 總體架構(gòu)開始,介紹了 Nginx 的主要組成部分和處理流程。然后介紹 Nginx 的 4 個進程,以及 Nginx 在啟動過程中這些進程都是如何產(chǎn)生的。



然后聚焦到最為主要的 Master 進程的啟動過程做了哪些具體的事情,特別是 Master 進程和 Worker、Cache Manager、Cache Load 之間的關(guān)系。



在進程之間的信號發(fā)送方式的章節(jié)中,我們建立了信號、發(fā)送信號、信號處理、信號掩碼的概念,這有助于理解進程之間的通信。



最后,趁熱打鐵把 Nginx 接受網(wǎng)絡(luò)請求以及進程之間如何合作處理請求的過程進行了講解。



作者:崔皓
簡介:十六年開發(fā)和架構(gòu)經(jīng)驗,曾擔(dān)任過惠普武漢交付中心技術(shù)專家,需求分析師,項目經(jīng)理,后在創(chuàng)業(yè)公司擔(dān)任技術(shù)/產(chǎn)品經(jīng)理。善于學(xué)習(xí),樂于分享。目前專注于技術(shù)架構(gòu)與研發(fā)管理。



本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。

架構(gòu)師社區(qū)

1736 篇文章

關(guān)注

發(fā)布文章

編輯精選

技術(shù)子站

關(guān)閉