天天看點

震撼!全網第一張源碼分析全景圖揭秘Nginx

震撼!全網第一張源碼分析全景圖揭秘Nginx

不管是C/C++技術棧,還是PHP,Java技術棧,從事後端開發的朋友對nginx一定不會陌生。

想要深入學習nginx,閱讀源碼一定是非常重要的一環,但nginx源碼量畢竟還是不算少,一不小心就容易陷入某個細節,迷失在茫茫碼海之中。

如果有一張地圖,讓我們開啟上帝視角,總覽全局,幫助我們快速學習整體架構結構,又能不至于迷失其中那就再好不過了!

看到這篇文章的你有福了,筆者花了不少時間,把這件事給做了,先來看個全貌(限于平台圖檔尺寸設定,這裡隻能看個大概,想擷取高清大圖請看文末):

下面選取一些關鍵部分來一窺神秘的nginx。

主程序啟動

nginx主程序啟動後,進行一系列的初始化,包括但不限于:

指令行參數解析

時間初始化

日志初始化

ssl初始化

作業系統相關初始化

一緻性hash表初始化

子產品編号處理

核心初始化

另外一個最重要的初始化由ngx_init_cycle()函數完成,該函數圍繞nginx中非常核心的一個全局資料結構ngx_cycle_t展開。

該函數完成了幾個核心初始化:

配置檔案解析

建立并監聽socket

初始化nginx各子產品

nginx核心子產品群

nginx是一個子產品化設計的軟體,優秀的架構設計使得nginx可以擴充非常多的子產品。

要一一描繪出這些子產品顯得有些雜亂和工作量巨大,僅選取一些關鍵核心子產品進行了展示:

每個子產品有一個支援的指令解析清單,在初始化過程中,主程序将會周遊所有子產品的指令清單,進行配置檔案中的指令解析,如經常用的ngx_http_proxy_module:

ngx_http_core_module子產品:

main函數的最後,根據是否啟用多程序模型,分别進入多程序版本的ngx_master_process_cycle和單程序版本的ngx_single_process_cycle()。

以常見的多程序版本為例,進入該函數後,首先設定程序名稱為:"master process",随後啟動各工作子程序。

啟動子程序

經過幾層封裝,最終通過fork啟動多個子程序:

除了工作子程序,還啟動了緩存管理程序。

之後主程序進入工作循環,周期性更新時間并檢查各全局标記,根據不同情況給子程序發送不同信号。

子程序工作循環

子程序啟動後,進入ngx_worker_process_cycle,進行一些工作程序的初始化,随後修改程序名稱為:"worker process"。

接着進入工作循環函數ngx_process_events_and_timers,在該函數中主要負責:

競争互斥鎖,拿到鎖的程序才能執行accept接受新的連接配接,以此在多程序之間解決驚群效應

通過epoll異步IO模型處理網絡IO事件,包括新的連接配接事件和已建立連接配接發生的讀寫事件

處理定時器隊列中到期的定時器事件,定時器通過紅黑樹的方式存儲

HTTP請求預處理

當連接配接有資料産生時,工作線程讀取socket中到來的資料,并根據HTTP協定格式進行解析,最終封裝成ngx_request_t請求對象,送出處理。

HTTP請求處理的11個階段

在nginx中各HTTP子產品是以挂載的形式串接而成,以流水線工作模式進行HTTP請求的處理,nginx将一個HTTP請求的處理劃分為11個階段。

typedef enum {

NGX_HTTP_POST_READ_PHASE = 0,
NGX_HTTP_SERVER_REWRITE_PHASE,
NGX_HTTP_FIND_CONFIG_PHASE,
NGX_HTTP_REWRITE_PHASE,
NGX_HTTP_POST_REWRITE_PHASE,
NGX_HTTP_PREACCESS_PHASE,
NGX_HTTP_ACCESS_PHASE,
NGX_HTTP_POST_ACCESS_PHASE,
NGX_HTTP_PRECONTENT_PHASE,
NGX_HTTP_CONTENT_PHASE,
NGX_HTTP_LOG_PHASE           

} ngx_http_phases;

每階段(部分階段保留,不允許挂載)允許多個子產品挂載,一個子產品也可以挂載到多個階段。是以,初次完成挂載的存儲結構是一個二維數組的形式。

不過在初始化過程中,ngx_http_init_phase_handlers函數将該二維數組轉換成了一維數組。下圖是nginx中各子產品挂載情況:

全景圖

最後,再來看一看全貌:

總結

nginx不僅是一款優秀的高性能web伺服器,對于C/C++技術棧的同學來說,還是一個很好的學習對象,其良好的架構設計,優美的代碼風格和經典的程式設計技法無一不值得細細品來。

不過限于筆者水準和時間有限,雖然号稱全景圖,但依然無法覆寫到nginx的方方面面,歡迎讀者朋友留言交流,讓此圖日漸完善,謝謝大家。

擷取完整高清大圖,可在公衆号裡回複“nginx”自動擷取。

原文位址

https://www.cnblogs.com/xuanyuan/p/12710715.html