Nginx學習筆記(十一):Nginx的架構設計
阿新 • • 發佈:2019-02-10
前言
開始學習書的第三部分,深入Nginx了,也越發在Nginx身上看到了之前實習公司所開發系統的影子,感謝過去的這段經歷。另外,越來越發現CSDN的是個好地方,看別人部落格的時候總能讓自己也熱血沸騰,在他們身上看到了自己缺少並且又難能可貴的品質,向他們學習。Nginx架構設計
這裡先說下Nginx設計時重視的幾個關鍵點:- 效能:包括網路效能,單詞請求的延遲性,網路效率;(名詞就不解釋了~)
- 可伸縮性:可通過新增元件來提升服務,或者允許元件之間具有互動功能;
- 簡單性:元件的簡單程度,便於理解和實現;
- 可修改性:包括可進化性,可擴充套件性,可定製性,可配置性,可重用性;
- 可見性:可監控關鍵元件的執行情況;
- 可移植性:跨平臺執行;
- 可靠性:在服務出現故障時,一個架構容易受到系統層面故障影響的程度;
模組化設計
高度模組化的設計是Nginx的架構基礎。在Nginx中,除了少量的核心程式碼,其他一切皆為模組。這一點在之前的模組開發的實踐中已經感受到了。 所有模組都遵循ngx_module_t的介面設計,並且所有模組間都是分層次、分類別的。 官方Nginx共有五大型別模組:核心模組、配置模組、事件模組、HTTP模組、mail模組。 它們都各具備相同的ngx_module_t介面,但在請求處理流程中的層次不相同。配置模組與核心模組由Nginx的框架程式碼定義。其中,配置模組是所有模組的基礎,它實現最基本的解析功能(即解析nginx.conf檔案)。然後,Nginx框架會呼叫核心模組,其他三種模組則不會與框架產生直接關係。如上圖示,事件模組、HTTP模組、mail模組在核心模組中分別都有一個自己的“代言人”,並在同類模組中有一個作為核心業務與管理功能的模組。比如,事件模組由其代言人ngx_events_module核心模組定義,但所有事件模組載入又由ngx_event_core_module負責。 在上圖中,配置模組與核心模組都是與Nginx框架密切相關的,是其他模組的基礎。而事件模組又是HTTP模組和mail模組的接觸。HTTP模組與mail模組更關注於應用層面,地位相似。
事件驅動架構
事件驅動架構,簡單來生活,就是由一些時間發生源產生事件,由一個或多個事件收集器來收集、分發時間,然後許多時間處理器會註冊自己感興趣的事件,同時會“消費”這些事件。 Nginx採用完全的事件驅動架構來處理業務,與傳統的Web伺服器不同。區別用圖示:- 傳統Web伺服器處理事件模型
- Nginx處理事件模型
請求的多階段非同步處理
請求的多階段非同步處理只能基於事件驅動架構,意思就是把一個請求的處理過程按照事件的觸發方式劃分為多個階段,每個階段都可以由事件收集、分發器來觸發。 非同步處理和多階段: 非同步處理與多階段的劃分是相輔相成的。可以這樣理解,當一個事件被分發到事件消費者中進行處理時,事件消費者處理完當前事件只是相當於處理完一個請求的某個階段,然後再等待核心通知,進而再次呼叫消費者處理... 請求的多階段非同步處理優勢: 這種設計可以使得每個程序都能全力進行,不會或者儘量少地出現程序休眠狀態。- 一旦出現程序休眠,必然減少併發處理事件的數目,進而會降低網路效能同時增加請求處理時間的平均時延;
- 程序如果休眠導致網路效能無法滿足業務需求,則系統只能通過增加程序來解決。這時,程序數目過多又將會導致作業系統的額外操作:程序間切換。頻繁地進行程序切換會嚴重消耗CPU資源;
- 休眠程序會使得程序佔用記憶體而不得釋放,這將導致系統可用記憶體下降,從而影響系統能夠處理的最大併發連線數;
- 將阻塞程序的方法按照相關的觸發事件分為兩個階段
- 將阻塞方法呼叫按照時間分解為多個階段的方法呼叫
- 在“無所事事”且必須等待系統的響應,從而導致程序空轉時,使用定時器劃分階段
- 如果阻塞方法完全無法繼續劃分,則必須使用獨立的程序執行這個阻塞方法
管理程序、多工作程序設計
Nginx採用一個master管理程序、多個worker工作程序的設計方式。如下圖:這種設計帶來的優勢:
- 1)利用多核系統的併發處理能力。多個Work程序可以佔用不同的CPU核心來工作,這樣提供網路效能,降低了請求時延。
- 2)負載均衡。一個請求到來時被分配到負載較輕的Worker程序中去處理。
- 3)管理程序負責監控工作程序狀態,並負責管理其行為。Master程序基本不佔用多少系統資源,它只負責啟動、停止、監控或使用其他行為來控制Worker程序。
平臺無關程式碼實現
Nginx重新封裝了日誌、各種基本資料結構(之前的筆記都有記錄)、常用演算法等。 在核心程式碼都使用了與作業系統無關的程式碼實現,在與作業系統相關的系統呼叫上則分別針對各個作業系統都有各自獨立的實現,這造就了Nginx的可移植性。記憶體池設計
以前第一次聽說的時候總覺得這是個很高階的東西,我現在突然明白了為什麼要有記憶體池設計了。很簡單,就是把多次向系統申請記憶體的操作整合成一次,從而減少向作業系統申請記憶體的次數,以及避免出現記憶體碎片。 記憶體池不負責回收記憶體池中已經分配出的記憶體。 然後在程式碼結束的最後,再統一釋放,即統一申請,統一釋放。這樣子,方便太多。。使用統一管道過濾器模式的HTTP過濾模組
其實就是過濾模組,這個完全可以看之前筆記《HTTP過濾模組》。每一個過濾模組的輸入輸出都是統一的介面,通過一種連結串列式的結構串聯在一起,但每個模組又各自獨立。 整個過程就是一個過濾模組處理完輸入的資料,然後通過統一介面傳給下一個模組。 這種統一管理過濾器的設計方式優點:- 整個HTTP過濾系統的輸入/輸出簡化為一個個過濾模組的簡單組合;
- 提供很好的可重用性,可將任意兩個HTTP過濾模組連線在一起;
- 容易維護與增強,在可驗證性與可測試性上更加友好,可以靈活變動過濾模組流水線來驗證功能;
- 完全支援併發執行;