不論是C/C++技術棧,仍是PHP,Java技術棧,從過後端開發的朋友對nginx必定不會陌生。nginx
想要深刻學習nginx,閱讀源碼必定是很是重要的一環,但nginx源碼量畢竟仍是不算少,一不當心就容易陷入某個細節,迷失在茫茫碼海之中。web
若是有一張地圖,讓咱們開啓上帝視角,總覽全局,幫助咱們快速學習總體框架結構,又能不至於迷失其中那就再好不過了!編程
看到這篇文章的你有福了,筆者花了很多時間,把這件事給作了,先來看個全貌(限於平臺圖片尺寸設定,這裏只能看個大概,想獲取高清大圖請看文末):後端
下面選取一些關鍵部分來一窺神祕的nginx。數組
nginx主進程啓動後,進行一系列的初始化,包括但不限於:緩存
另一個最重要的初始化由ngx_init_cycle()
函數完成,該函數圍繞nginx中很是核心的一個全局數據結構ngx_cycle_t
展開。服務器
該函數完成了幾個核心初始化:網絡
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
,在該函數中主要負責:
當鏈接有數據產生時,工做線程讀取socket中到來的數據,並根據HTTP協議格式進行解析,最終封裝成ngx_request_t請求對象,提交處理。
在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」自動獲取。
Python一鍵轉Jar包,Java調用Python新姿式!