# 3.4 Nginx的模塊化體系
### 一、模塊體系
Nginx的內部結構是由核心部分和一系列功能模塊組成的,這樣可以使得每個模塊的功能相對簡單,便于對系統進行功能擴展,各模塊之間的關系如下圖:

nginx core實現了底層的通訊協議,為其它模塊和Nginx進程構建了基本的運行時環境,并且構建了其它各模塊的協作基礎。
http模塊和mail模塊位于nginx core和各功能模塊的中間層,這2個模塊在nginx core之上實現了另外一層抽象,分別處理與http協議和email相關協議(SMTP/IMAP/POP3)有關的事件,并且確保這些事件能被以正確的順序調用其它的一些功能模塊。
nginx功能模塊基本上分為如下幾種類型:
(1)event module:搭建了獨立于操作系統的事件處理機制的框架,以及提供了各具體事件的處理,包括ngx_event_module、ngx_event_core_module和ngx_epoll_module等,Nginx具體使用何種事件處理模塊,這依賴于具體的操作系統和編譯選項。
(2)phase handler:此類型的模塊也被直接稱為handler模塊,主要負責處理客戶端請求并產生待響應內容,比如ngx_http_module模塊,負責客戶端的靜態頁面請求處理并將對應的磁盤文件準備為響應內容輸出。
(3)output filter:也稱為filter模塊,主要是負責對輸出的內容進行處理,可以對輸出進行修改,比如可以實現對輸出的所有html頁面增加預定義的footbar一類的工作,或者對輸出的圖片的URL進行替換之類的工作。
(4)upstream:實現反向代理功能,將真正的請求轉發到后端服務器上,并從后端服務器上讀取響應,發回客戶端,upstream模塊是一種特殊的handler,只不過響應內容不是真正由自己產生的,而是從后端服務器上讀取的。
(5)load-balancer:負載均衡模塊,實現特定的算法,在眾多的后端服務器中,選擇一個服務器出來作為某個請求的轉發服務器。
(6)extend module:根據特定業務需要編寫的第三方模塊。
### 二、請求處理
下面將會以http請求處理為例來說明請求、配置和模塊是如何串起來的。
當Nginx讀取到一個HTTP Request的header時,首先查找與這個請求關聯的虛擬主機的配置,如果找到了則這個請求將會經歷以下幾個階段的處理(phase handlers):
**NGX_HTTP_POST_READ_PHASE**:讀取請求內容階段
**NGX_HTTP_SERVER_REWRITE_PHASE**:Server請求地址重寫階段
**NGX_HTTP_FIND_CONFIG_PHASE**:配置查找階段
**NGX_HTTP_REWRITE_PHASE**:Location請求地址重寫階段
**NGX_HTTP_POST_REWRITE_PHASE**:請求地址重寫提交階段
**NGX_HTTP_PREACCESS_PHASE**:訪問權限檢查準備階段
**NGX_HTTP_ACCESS_PHASE**:訪問權限檢查階段
**NGX_HTTP_POST_ACCESS_PHASE**:訪問權限檢查提交階段
**NGX_HTTP_TRY_FILES_PHASE**:配置項try_files處理階段
**NGX_HTTP_CONTENT_PHASE**:內容產生階段
**NGX_HTTP_LOG_PHASE**:日志模塊處理階段
在內容產生階段,為了給一個request產生正確的response,Nginx必須把這個請求交給一個合適的content handler去處理。如果這個request對應的location在配置文件中被明確指定了一個content handler,那么Nginx就可以通過對location的匹配,直接找到這個對應的handler,并把這個request交給這個content handler去處理。這樣的配置指令包括perl、flv、proxy_pass、mp4等。
如果一個request對應的location并沒有直接配置的content handler,那么Nginx依次作如下嘗試:
(1)如果一個location里面有配置random_index on,那么隨機選擇一個文件發送給客戶端。
(2)如果一個location里面有配置index指令,那么發送index指令指定的文件給客戶端。
(3)如果一個location里面有配置autoindex on,那么就發送請求地址對應的服務端路徑下的文件列表給客戶端。
(4)如果這個request對應的location上有設置gzip_static on,那么就查找是否有對應的.gz文件存在,如果有的話,就發送這個給客戶端(客戶端支持gzip的情況下)。
(5)請求的URI如果對應一個靜態文件,static module就發送靜態文件的內容到客戶端。
內容產生階段完成以后,生成的輸出會被傳遞到filter模塊去進行處理。filter模塊也是與location相關的。所有的fiter模塊都被組織成一條鏈。輸出會依次穿越所有的filter,直到有一個filter模塊的返回值表明已經處理完成。接下來就可以發送response給客戶端了。