摘要:請(qǐng)求的多階段異步處理多階段異步處理請(qǐng)求與事件驅(qū)動(dòng)架構(gòu)是密切相關(guān)的,也就是說(shuō),請(qǐng)求的多階段異步處理只能基于事件驅(qū)動(dòng)架構(gòu)實(shí)現(xiàn)。
前言
最近在讀 Nginx 相關(guān)的書(shū)籍,做一下讀書(shū)筆記。
Nginx 作為業(yè)界知名的高性能服務(wù)器,被廣泛的應(yīng)用。它的高性能正是由于其優(yōu)秀的架構(gòu)設(shè)計(jì),其架構(gòu)主要包括這幾點(diǎn):模塊化設(shè)計(jì)、事件驅(qū)動(dòng)架構(gòu)、請(qǐng)求的多階段異步處理、管理進(jìn)程與多工作進(jìn)程設(shè)計(jì)、內(nèi)存池的設(shè)計(jì),以下內(nèi)容依次進(jìn)行說(shuō)明。
模塊化設(shè)計(jì)高度模塊化的設(shè)計(jì)是 Nginx 的架構(gòu)基礎(chǔ)。在 Nginx 中,除了少量的核心代碼,其他一切皆為模塊。
所有模塊間是分層次、分類(lèi)別的,Nginx 官方共有五大類(lèi)型的模塊:核心模塊、配置模塊、事件模塊、HTTP 模塊、mail 模塊。它們之間的關(guān)系如下:
在這 5 種模塊中,配置模塊和核心模塊是與 Nginx 框架密切相關(guān)的。而事件模塊則是 HTTP 模塊和 mail 模塊的基礎(chǔ)。HTTP 模塊和 mail 模塊的“地位”類(lèi)似,它們都是更關(guān)注于應(yīng)用層面。
事件驅(qū)動(dòng)架構(gòu)事件驅(qū)動(dòng)架構(gòu),簡(jiǎn)單的說(shuō)就是由一些事件發(fā)生源來(lái)產(chǎn)生事件,由事件收集器來(lái)收集、分發(fā)事件,然后由事件處理器來(lái)處理這些事件(事件處理器需要先在事件收集器里注冊(cè)自己想處理的事件)。
對(duì)于 Nginx 服務(wù)器而言,一般由網(wǎng)卡、磁盤(pán)產(chǎn)生事件,Nginx 中的事件模塊將負(fù)責(zé)事件的收集、分發(fā)操作;而所有的模塊都可能是事件消費(fèi)者,它們首先需要向事件模塊注冊(cè)感興趣的事件類(lèi)型,這樣,在有事件產(chǎn)生時(shí),事件模塊會(huì)把事件分發(fā)到相應(yīng)的模塊中進(jìn)行處理。
對(duì)于傳統(tǒng) web 服務(wù)器(如 Apache)而言,采用的所謂事件驅(qū)動(dòng)往往局限在 TCP 連接建立、關(guān)閉事件上,一個(gè)連接建立以后,在其關(guān)閉之前的所有操作都不再是事件驅(qū)動(dòng),這時(shí)會(huì)退化成按順序執(zhí)行每個(gè)操作的批處理模式,這樣每個(gè)請(qǐng)求在連接建立后都將始終占用著系統(tǒng)資源,直到關(guān)閉才會(huì)釋放資源。這種請(qǐng)求占用著服務(wù)器資源等待處理的模式會(huì)造成服務(wù)器資源極大的浪費(fèi)。如下圖所示,傳統(tǒng) web 服務(wù)器往往把一個(gè)進(jìn)程或線(xiàn)程作為時(shí)間消費(fèi)者,當(dāng)一個(gè)請(qǐng)求產(chǎn)生的事件被該進(jìn)程處理時(shí),直到這個(gè)請(qǐng)求處理結(jié)束時(shí),進(jìn)程資源都將被這一請(qǐng)求所占用。比較典型的例子如 Apache 同步阻塞的多進(jìn)程模式就是這樣的。
傳統(tǒng) web 服務(wù)器處理事件的簡(jiǎn)單模型(矩形代表進(jìn)程):
Nginx 采用事件驅(qū)動(dòng)架構(gòu)處理業(yè)務(wù)的方式與傳統(tǒng)的 web 服務(wù)器是不同的。它不使用進(jìn)程或者線(xiàn)程來(lái)作為事件消費(fèi)者,所謂的事件消費(fèi)者只能是某個(gè)模塊。只有事件收集、分發(fā)器才有資格占用進(jìn)程資源,它們會(huì)在分發(fā)某個(gè)事件時(shí)調(diào)用事件消費(fèi)模塊使用當(dāng)前占用的進(jìn)程資源,如下圖所示,該圖中列出了 5 個(gè)不同的事件,在事件收集、分發(fā)者進(jìn)程的一次處理過(guò)程中,這 5 個(gè)事件按照順序被收集后,將開(kāi)始使用當(dāng)前進(jìn)程分發(fā)事件,從而調(diào)用相應(yīng)的事件消費(fèi)者來(lái)處理事件。當(dāng)然,這種分發(fā)、調(diào)用也是有序的。
Nginx 處理事件的簡(jiǎn)單模型:
由上圖可以看出,處理請(qǐng)求事件時(shí),Nginx 的事件消費(fèi)者只是被事件分發(fā)者進(jìn)程短期調(diào)用而已,這種設(shè)計(jì)使得網(wǎng)絡(luò)性能、用戶(hù)感知的請(qǐng)求時(shí)延都得到了提升,每個(gè)用戶(hù)的請(qǐng)求所產(chǎn)生的事件會(huì)及時(shí)響應(yīng),整個(gè)服務(wù)器的網(wǎng)絡(luò)吞吐量都會(huì)由于事件的及時(shí)響應(yīng)而增大。當(dāng)然,這也帶來(lái)一定的要求,即每個(gè)事件消費(fèi)者都不能有阻塞行為,否則將會(huì)由于長(zhǎng)時(shí)間占用事件分發(fā)者進(jìn)程而導(dǎo)致其他事件得不到及時(shí)響應(yīng),Nginx 的非阻塞特性就是由于它的模塊都是滿(mǎn)足這個(gè)要求的。
請(qǐng)求的多階段異步處理多階段異步處理請(qǐng)求與事件驅(qū)動(dòng)架構(gòu)是密切相關(guān)的,也就是說(shuō),請(qǐng)求的多階段異步處理只能基于事件驅(qū)動(dòng)架構(gòu)實(shí)現(xiàn)。多階段異步處理就是把一個(gè)請(qǐng)求的處理過(guò)程按照事件的觸發(fā)方式劃分為多個(gè)階段,每個(gè)階段都可以由事件收集、分發(fā)器來(lái)觸發(fā)。
處理獲取靜態(tài)文件的 HTTP 請(qǐng)求時(shí)切分的階段及各階段的觸發(fā)事件如下所示:
這個(gè)例子中,該請(qǐng)求大致分為 7 個(gè)階段,這些階段是可以重復(fù)發(fā)生的,因此,一個(gè)下載靜態(tài)資源請(qǐng)求可能會(huì)由于請(qǐng)求數(shù)據(jù)過(guò)大,網(wǎng)速不穩(wěn)定等因素而被分解為成百上千個(gè)上圖所列出的階段。
異步處理和多階段是相輔相成的,只有把請(qǐng)求分為多個(gè)階段,才有所謂的異步處理。當(dāng)一個(gè)時(shí)間被分發(fā)到事件消費(fèi)者中進(jìn)行處理時(shí),事件消費(fèi)者處理完這個(gè)事件只相當(dāng)于處理完 1 個(gè)請(qǐng)求的階段。什么時(shí)候可以處理下一個(gè)階段呢?這只能等待內(nèi)核的通知,即當(dāng)下一次事件出現(xiàn)時(shí),epoll 等事件分發(fā)器將會(huì)獲取到通知,然后去調(diào)用事件消費(fèi)者進(jìn)行處理。
管理進(jìn)程、多工作進(jìn)程設(shè)計(jì)Nginx 在啟動(dòng)后,會(huì)有一個(gè) master 進(jìn)程和多個(gè) worker 進(jìn)程。master 進(jìn)程主要用來(lái)管理worker 進(jìn)程,包括接收來(lái)自外界的信號(hào),向各 worker 進(jìn)程發(fā)送信號(hào),監(jiān)控 worker 進(jìn)程的運(yùn)行狀態(tài)以及啟動(dòng) worker 進(jìn)程。 worker 進(jìn)程是用來(lái)處理來(lái)自客戶(hù)端的請(qǐng)求事件。多個(gè) worker 進(jìn)程之間是對(duì)等的,它們同等競(jìng)爭(zhēng)來(lái)自客戶(hù)端的請(qǐng)求,各進(jìn)程互相獨(dú)立,一個(gè)請(qǐng)求只能在一個(gè) worker 進(jìn)程中處理。worker 進(jìn)程的個(gè)數(shù)是可以設(shè)置的,一般會(huì)設(shè)置與機(jī)器 CPU 核數(shù)一致,這里面的原因與事件處理模型有關(guān)。Nginx 的進(jìn)程模型,可由下圖來(lái)表示:
在服務(wù)器上查看 Nginx 進(jìn)程:
這種設(shè)計(jì)帶來(lái)以下優(yōu)點(diǎn):
1) 利用多核系統(tǒng)的并發(fā)處理能力
現(xiàn)代操作系統(tǒng)已經(jīng)支持多核 CPU 架構(gòu),這使得多個(gè)進(jìn)程可以分別占用不同的 CPU 核心來(lái)工作。Nginx 中所有的 worker 工作進(jìn)程都是完全平等的。這提高了網(wǎng)絡(luò)性能、降低了請(qǐng)求的時(shí)延。
2) 負(fù)載均衡
多個(gè) worker 工作進(jìn)程通過(guò)進(jìn)程間通信來(lái)實(shí)現(xiàn)負(fù)載均衡,即一個(gè)請(qǐng)求到來(lái)時(shí)更容易被分配到負(fù)載較輕的 worker 工作進(jìn)程中處理。這也在一定程度上提高了網(wǎng)絡(luò)性能、降低了請(qǐng)求的時(shí)延。
3) 管理進(jìn)程會(huì)負(fù)責(zé)監(jiān)控工作進(jìn)程的狀態(tài),并負(fù)責(zé)管理其行為
管理進(jìn)程不會(huì)占用多少系統(tǒng)資源,它只是用來(lái)啟動(dòng)、停止、監(jiān)控或使用其他行為來(lái)控制工作進(jìn)程。首先,這提高了系統(tǒng)的可靠性,當(dāng) worker 進(jìn)程出現(xiàn)問(wèn)題時(shí),管理進(jìn)程可以啟動(dòng)新的工作進(jìn)程來(lái)避免系統(tǒng)性能的下降。其次,管理進(jìn)程支持 Nginx 服務(wù)運(yùn)行中的程序升級(jí)、配置項(xiàng)修改等操作,這種設(shè)計(jì)使得動(dòng)態(tài)可擴(kuò)展性、動(dòng)態(tài)定制性較容易實(shí)現(xiàn)。
內(nèi)存池的設(shè)計(jì)為了避免出現(xiàn)內(nèi)存碎片,減少向操作系統(tǒng)申請(qǐng)內(nèi)存的次數(shù)、降低各個(gè)模塊的開(kāi)發(fā)復(fù)雜度,Nginx 設(shè)計(jì)了簡(jiǎn)單的內(nèi)存池,它的作用主要是把多次向系統(tǒng)申請(qǐng)內(nèi)存的操作整合成一次,這大大減少了 CPU 資源的消耗,同時(shí)減少了內(nèi)存碎片。
因此,通常每一個(gè)請(qǐng)求都有一個(gè)簡(jiǎn)易的獨(dú)立內(nèi)存池(如每個(gè) TCP 連接都分配了一個(gè)內(nèi)存池),而在請(qǐng)求結(jié)束時(shí)則會(huì)銷(xiāo)毀整個(gè)內(nèi)存池,把曾經(jīng)分配的內(nèi)存一次性歸還給操作系統(tǒng)。這種設(shè)計(jì)大大提高了模塊開(kāi)發(fā)的簡(jiǎn)單些,因?yàn)樵谀K申請(qǐng)內(nèi)存后不用關(guān)心它的釋放問(wèn)題;而且因?yàn)榉峙鋬?nèi)存次數(shù)的減少使得請(qǐng)求執(zhí)行的時(shí)延得到了降低。同時(shí),通過(guò)減少內(nèi)存碎片,提高了內(nèi)存的有效利用率和系統(tǒng)可處理的并發(fā)連接數(shù),從而增強(qiáng)了網(wǎng)絡(luò)性能。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/11970.html
摘要:請(qǐng)求的多階段異步處理多階段異步處理請(qǐng)求與事件驅(qū)動(dòng)架構(gòu)是密切相關(guān)的,也就是說(shuō),請(qǐng)求的多階段異步處理只能基于事件驅(qū)動(dòng)架構(gòu)實(shí)現(xiàn)。 前言 最近在讀 Nginx 相關(guān)的書(shū)籍,做一下讀書(shū)筆記。 Nginx 作為業(yè)界知名的高性能服務(wù)器,被廣泛的應(yīng)用。它的高性能正是由于其優(yōu)秀的架構(gòu)設(shè)計(jì),其架構(gòu)主要包括這幾點(diǎn):模塊化設(shè)計(jì)、事件驅(qū)動(dòng)架構(gòu)、請(qǐng)求的多階段異步處理、管理進(jìn)程與多工作進(jìn)程設(shè)計(jì)、內(nèi)存池的設(shè)計(jì),以下內(nèi)...
摘要:常規(guī)的網(wǎng)絡(luò)應(yīng)用設(shè)計(jì)都是為每個(gè)連接分配一個(gè)線(xiàn)程或進(jìn)程。深入理解進(jìn)程每個(gè)進(jìn)程都是用配置進(jìn)行初始化的,并且由主進(jìn)程提供了一組監(jiān)聽(tīng)套接字。套接字上發(fā)生事件后,進(jìn)程開(kāi)始進(jìn)行處理監(jiān)聽(tīng)套接字上的事件意味著有個(gè)客戶(hù)端發(fā)起了一盤(pán)新的象棋游戲。 NGINX在web性能上的表現(xiàn)尤為出眾,這完全得益于其設(shè)計(jì)方式,許多web和應(yīng)用服務(wù)器都是基于線(xiàn)程或進(jìn)程這種簡(jiǎn)單的架構(gòu),NGINX用了一種精妙的事件驅(qū)動(dòng)架構(gòu),在現(xiàn)...
摘要:阻塞,非阻塞首先,阻塞這個(gè)詞來(lái)自操作系統(tǒng)的線(xiàn)程進(jìn)程的狀態(tài)模型網(wǎng)絡(luò)爬蟲(chóng)基本原理一后端掘金網(wǎng)絡(luò)爬蟲(chóng)是捜索引擎抓取系統(tǒng)的重要組成部分。每門(mén)主要編程語(yǔ)言現(xiàn)未來(lái)已到后端掘金使用和在相同環(huán)境各加載多張小圖片,性能相差一倍。 2016 年度小結(jié)(服務(wù)器端方向)| 掘金技術(shù)征文 - 后端 - 掘金今年年初我花了三個(gè)月的業(yè)余時(shí)間用 Laravel 開(kāi)發(fā)了一個(gè)項(xiàng)目,在此之前,除了去年換工作準(zhǔn)備面試時(shí),我并...
摘要:阻塞,非阻塞首先,阻塞這個(gè)詞來(lái)自操作系統(tǒng)的線(xiàn)程進(jìn)程的狀態(tài)模型網(wǎng)絡(luò)爬蟲(chóng)基本原理一后端掘金網(wǎng)絡(luò)爬蟲(chóng)是捜索引擎抓取系統(tǒng)的重要組成部分。每門(mén)主要編程語(yǔ)言現(xiàn)未來(lái)已到后端掘金使用和在相同環(huán)境各加載多張小圖片,性能相差一倍。 2016 年度小結(jié)(服務(wù)器端方向)| 掘金技術(shù)征文 - 后端 - 掘金今年年初我花了三個(gè)月的業(yè)余時(shí)間用 Laravel 開(kāi)發(fā)了一個(gè)項(xiàng)目,在此之前,除了去年換工作準(zhǔn)備面試時(shí),我并...
摘要:作為面試官,我是如何甄別應(yīng)聘者的包裝程度語(yǔ)言和等其他語(yǔ)言的對(duì)比分析和主從復(fù)制的原理詳解和持久化的原理是什么面試中經(jīng)常被問(wèn)到的持久化與恢復(fù)實(shí)現(xiàn)故障恢復(fù)自動(dòng)化詳解哨兵技術(shù)查漏補(bǔ)缺最易錯(cuò)過(guò)的技術(shù)要點(diǎn)大掃盲意外宕機(jī)不難解決,但你真的懂?dāng)?shù)據(jù)恢復(fù)嗎每秒 作為面試官,我是如何甄別應(yīng)聘者的包裝程度Go語(yǔ)言和Java、python等其他語(yǔ)言的對(duì)比分析 Redis和MySQL Redis:主從復(fù)制的原理詳...
閱讀 2862·2021-10-21 09:38
閱讀 2761·2021-10-11 10:59
閱讀 3048·2021-09-27 13:36
閱讀 1667·2021-08-23 09:43
閱讀 801·2019-08-29 14:14
閱讀 3040·2019-08-29 12:13
閱讀 3209·2019-08-29 12:13
閱讀 318·2019-08-26 12:24