1. 程式人生 > >Nginx原始碼分析—架構設計思想

Nginx原始碼分析—架構設計思想

Nginx原始碼分析—架構設計思想

我任務nginx的原始碼可以分為三個部分,一個是在ngx_init_cycle之前,這個也算是為了重新啟動nginx而準備的程式碼,比如說在這個時候可以接受外部的訊號,也可以儲存傳遞的引數,等等,當然在以後的函式中也考慮了是否正在重啟nginx。

         至於ngx_init_cycle這個函式,是一個很龐大的函式,在這個函式中可以看到呼叫了各個模組的鉤子函式,這裡又設計到了nginx結構體的使用,比如所有的模組都是ngx_module_t這個結構體,但是這個結構體中的ctx變數和commands type這三個變數使得各個module的功能又有所不同。將每一個模組都有所歸類

         對於一個標準的HTTP請求中,nginx框架試圖結束完整的HTTP頭部,並在接收到完整的HTPP頭部後將請求分發到具體的HTTP模組中處理,最常見的即使根據請求的URI(URI在HTTP請求的頭部資訊中)和ngin.conf裡的location配置項的匹配度來決定如何分發。

         HTTP模組間資料流的傳遞,各個模組之間的寫通過工作,配置檔案中的Location塊決定了匹配某種URI的請求將會由相應的HTTP模組處理,因此,執行時HTTP框架會在接收完畢HTTP請求的頭部後,將請求的URI與配置檔案中的所有location進行匹配,匹配後再根據Location{}內的配置項選擇HTTP模組來呼叫。

         對於ngx_moudle_t結構體中的init_module  init_process 函式指標,前者是在初始化所有模組時被呼叫,後者是在worker程序已經產生時被呼叫,這兩個函式指標之後再ngx_core_event_module模組中實現了這幾個呼叫時和nginx框架相關的,對於一個HTTP模組,NGX_HTTP_MODULE,ngx_module_t中的ctx指向ngx_http_module_t型別的結構體,這個結構體中有8個函式指標,nginx狂a級會在不同的時刻呼叫這個8個回撥來讀取過載配置檔案。

         一個HTTP請求會被許多個配置項控制,實際上這是因為一個HTTP請求可以被許多個HTTP模組同時處理,這樣就會有一個先手順序問題。由於同一個配置項可以從屬與許多個server location配置快,那麼這個配置項將會針對不同的請求起作用。自己有很大的自由來定義自己的模組如何介入HTTP請求的處理,

         可以這麼認為,某一個配置項,在不同的層次有不同的作用域,配置項決定了自己感興趣的HTTP請求。

         可以這麼理解配置項,配置項是對某一類HTTP請求感興趣,這個配置項放到某一個配置塊內,當某一類HTTP請求到達後進行匹配,根據配置項來判斷有哪些模組對自己這個HTTP請求感興趣,那麼系統就進行控制對這個HTTP請求呼叫這個配置項對應的HTTP模組

         對於一個有引數的配置項,在NGINX中定義了14個常用的型別來標識配置項中的引數型別,也有對應的引數來處理這些引數。

http{}塊下有一個ngx_http_conf_ctx_t結構,而每一個serve{}塊下也有一個ngx_http_conf_ctx_t結構

         NGINX原始碼分析—過濾模組的意義

         HTTP框架允許普通的HTTP處理模組介入其中的7個階段處理請求,但是普通大部分HTTP模組(官方模組或者第三方模組)都只在NGX_HTTP_CONTENT_PHASE階段處理請求,HTTP模組有兩種介入方法,第一種是,任意一個HTTP模組會對所有的使用者請求產生作用,第二中方法,只對請求的URI匹配了nginx.conf中某些location表示式下的HTTP模組起作用,大部分模組都使用上述的第二種方法處理請求,這種方法的特點是一種請求僅由一個HTTP模組(在NGX_HTTP_CONTENT_PHASE階段)處理。如果希望多個HTTP模組共同處理一個請求,則多半是由subrequest功能來完成,即將原始請求分為多個子請求,每個子請求再由一個HTTP模組在NGX_HTTP_CONTENT_PHASE階段處理。

         對於HTTP過濾模組則不同,一個請求可以被任意個HTTP過濾模組處理,因此,普通的HTTP模組更傾向於完成請求的核心功能,如static模組複製靜態檔案的處理,HTTP過濾模組則處理一些附加的功能,如gzip過濾模組可以把傳送給使用者的靜態檔案進行gzip壓縮後在發出去,Image_filter這個第三方過濾模組可以將圖片類的靜態檔案製作成縮圖。而且,這些過濾模組的效果是可以根據需要疊加的,比如先由Not_modify過濾模組處理請求中的瀏覽器快取資訊,再交給range過濾模組處理HTTP range協議(支援斷點續傳),然後交由gzip過濾模組進行壓縮,一個請求經由各HTTP過濾模組流水線般地依次進行處理了。

         在普通HTTP模組處理請求完畢,並呼叫ngx_http_send_header傳送HTTP頭部,或者呼叫ngx_http_output_filter傳送HTTP包體時,才會由這兩個方法依次呼叫所有的HTTP過濾模組處理這個請求,因此,HTTP過濾模組僅處理伺服器發往客戶端的HTTP響應,而不處理客戶端發往伺服器的HTTP請求

         NGINX在進行迴應時,分為頭部迴應和包體迴應,那麼過濾連結串列也分為兩個部分,對於某一個過濾模組,插入的時候都是插入這個連結串列的首部,所以,HTTP過濾模組越靠後,在實際執行請求時就越優先執行,以為在初始化HTTP過濾模組式,每一個HTTP過濾模組都是將自己插入到整個單鏈表的首部。