Nginx 請求處理階段

Nginx 處理每一個(gè)用戶請求時(shí),都是按照若干個(gè)不同階段(phase)依次處理的,而不是根據(jù)配置文件上的順序。 Nginx 處理請求的過程一共劃分為 11 個(gè)階段,按照執(zhí)行順序依次是: post-read、server-rewrite、find-config、rewrite、post-rewrite、 preaccess、access、post-access、try-files、content、log.

Nginx 處理請求的過程一共劃分為 11 個(gè)階段,按照執(zhí)行順序依次是 post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、try-files、content 以及 log。

1、post-read

最先執(zhí)行的 post-read 階段在 Nginx 讀取并解析完請求頭(request headers)之后就立即開始運(yùn)行。例如:使用了 ngx_realip 模塊提供的 set_real_ip_fromreal_ip_header 這兩條配置指令

2、server-rewrite

由于 server-rewrite 階段位于 post-read 階段之后,所以 server 配置塊中的 set 指令也就總是運(yùn)行在 ngx_realip 模塊改寫請求的來源地址之后。

3、find-config

這個(gè)階段并不支持 Nginx 模塊注冊處理程序,而是由 Nginx 核心來完成當(dāng)前請求與 location 配置塊之間的配對工作。換句話說,在此階段之前,請求并沒有與任何 location 配置塊相關(guān)聯(lián)。因此,對于運(yùn)行在 find-config 階段之前的 post-read 和 server-rewrite 階段來說,只有 server 配置塊以及更外層作用域中的配置指令才會(huì)起作用。這就是為什么只有寫在 server 配置塊中的 ngx_rewrite 模塊的指令才會(huì)運(yùn)行在 server-rewrite 階段,這也是為什么前面所有例子中的 ngx_realip 模塊的指令也都特意寫在了 server 配置塊中,以確保其注冊在 post-read 階段的處理程序能夠生效。

4、rewrite

由于 Nginx 已經(jīng)在 find-config 階段完成了當(dāng)前請求與 location 的配對,所以從 rewrite 階段開始,location 配置塊中的指令便可以產(chǎn)生作用。當(dāng) ngx_rewrite 模塊的指令用于 location 塊中時(shí),便是運(yùn)行在這個(gè) rewrite 階段。

5、post-rewrite

這個(gè)階段也像 find-config 階段那樣不接受 Nginx 模塊注冊處理程序,而是由 Nginx 核心完成 rewrite 階段所要求的“內(nèi)部跳轉(zhuǎn)”操作(如果 rewrite 階段有此要求的話)。例如:通過 rewrite 指令把當(dāng)前請求的 URI 無條件地改寫為 /bar,同時(shí)發(fā)起一個(gè)“內(nèi)部跳轉(zhuǎn)”,最終跳進(jìn)了 location /bar 中。這里比較有趣的地方是“內(nèi)部跳轉(zhuǎn)”的工作原理?!皟?nèi)部跳轉(zhuǎn)”本質(zhì)上其實(shí)就是把當(dāng)前的請求處理階段強(qiáng)行倒退到 find-config 階段,以便重新進(jìn)行請求 URI 與 location 配置塊的配對。

6、preaccess

該階段在 access 階段之前執(zhí)行,故名 preaccess.標(biāo)準(zhǔn)模塊 ngx_limit_reqngx_limit_zone 就運(yùn)行在此階段,前者可以控制請求的訪問頻度,而后者可以限制訪問的并發(fā)度。

7、access

標(biāo)準(zhǔn)模塊 ngx_access、第三方模塊 ngx_auth_request 以及第三方模塊 ngx_luaaccess_by_lua 指令就運(yùn)行在這個(gè)階段。

8、 post-access

這個(gè)階段也和 post-rewrite 階段類似,并不支持 Nginx 模塊注冊處理程序,而是由 Nginx 核心自己完成一些處理工作。post-access 階段主要用于配合 access 階段實(shí)現(xiàn)標(biāo)準(zhǔn) ngx_http_core 模塊提供的配置指令 satisfy 的功能。對于多個(gè) Nginx 模塊注冊在 access 階段的處理程序, satisfy 配置指令可以用于控制它們彼此之間的協(xié)作方式。比如模塊 A 和 B 都在 access 階段注冊了與訪問控制相關(guān)的處理程序,那就有兩種協(xié)作方式,一是模塊 A 和模塊 B 都得通過驗(yàn)證才算通過,二是模塊 A 和模塊 B 只要其中任一個(gè)通過驗(yàn)證就算通過。第一種協(xié)作方式稱為 all 方式(或者說“與關(guān)系”),第二種方式則被稱為 any 方式(或者說“或關(guān)系”)。默認(rèn)情況下,Nginx 使用的是 all 方式。

9、try-files

這個(gè)階段專門用于實(shí)現(xiàn)標(biāo)準(zhǔn)配置指令 try_files 的功能,并不支持 Nginx 模塊注冊處理程序。try_files 指令接受兩個(gè)以上任意數(shù)量的參數(shù),每個(gè)參數(shù)都指定了一個(gè) URI. 這里假設(shè)配置了 N 個(gè)參數(shù),則 Nginx 會(huì)在 try-files 階段,依次把前 N-1 個(gè)參數(shù)映射為文件系統(tǒng)上的對象(文件或者目錄),然后檢查這些對象是否存在。一旦 Nginx 發(fā)現(xiàn)某個(gè)文件系統(tǒng)對象存在,就會(huì)在 try-files 階段把當(dāng)前請求的 URI 改寫為該對象所對應(yīng)的參數(shù) URI(但不會(huì)包含末尾的斜杠字符,也不會(huì)發(fā)生 “內(nèi)部跳轉(zhuǎn)”)。如果前 N-1 個(gè)參數(shù)所對應(yīng)的文件系統(tǒng)對象都不存在,try-files 階段就會(huì)立即發(fā)起“內(nèi)部跳轉(zhuǎn)”到最后一個(gè)參數(shù)(即第 N 個(gè)參數(shù))所指定的 URI.通過 root 配置指令所指定的“文檔根目錄”進(jìn)行映射。例如,當(dāng)“文檔根目錄”是 /var/www/ 的時(shí)候,請求 URI /foo/bar 會(huì)被映射為文件 /var/www/foo/bar,而請求 URI /foo/baz/ 則會(huì)被映射為目錄 /var/www/foo/baz/. 注意這里是如何通過 URI 末尾的斜杠字符是否存在來區(qū)分“目錄”和“文件”的。

10、content

Nginx 的 content 階段是所有請求處理階段中最為重要的一個(gè),因?yàn)檫\(yùn)行在這個(gè)階段的配置指令一般都肩負(fù)著生成“內(nèi)容”(content)并輸出 HTTP 響應(yīng)的使命。正因?yàn)槠渲匾裕@個(gè)階段的配置指令也異常豐富。echo、 Nginx 變量漫談(二) 中接觸到的 echo_exec 指令, Nginx 變量漫談(三) 中接觸到的 proxy_pass 指令,Nginx 變量漫談(五) 中介紹過的 echo_location 指令,以及 Nginx 變量漫談(七) 中介紹過的 content_by_lua。

11、log

log階段處理,比如記錄訪問量/統(tǒng)計(jì)平均響應(yīng)時(shí)間。log_by_lua

轉(zhuǎn)載地址
轉(zhuǎn)載地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容