大多數 Nginx 新手都會頻繁遇到這樣一個困惑,那就是當同一個 <code>location</code> 配置塊使用了多個 Nginx 子產品的配置指令時,這些指令的執行順序很可能會跟它們的書寫順序大相徑庭。于是許多人選擇了“試錯法”,然後他們的配置檔案就時常被改得一片狼藉。這個系列的教程就旨在幫助讀者逐漸地了解這些配置指令背後的執行時間和先後順序的奧秘。
現在就來看這樣一個令人困惑的例子:
我們看到,語句 <code>set $a 56</code> 似乎在第一條 <code>echo $a</code> 語句之前就執行過了。這究竟是為什麼呢?難道我們遇到了 Nginx 中的一個 bug?
顯然,這裡并沒有 Nginx 的 bug;要了解這裡發生的事情,就首先需要知道 Nginx 處理每一個使用者請求時,都是按照若幹個不同階段(phase)依次處理的。
Nginx 的請求處理階段共有 11 個之多,我們先介紹其中 3 個比較常見的。按照它們執行時的先後順序,依次是 <code>rewrite</code> 階段、<code>access</code> 階段以及 <code>content</code> 階段(後面我們還有機會見到其他更多的處理階段)。
回到剛才那個例子,
實際的執行順序應當是
為了進一步驗證這一點,我們不妨借助 Nginx 的“調試日志”來一窺 Nginx 的實際執行過程。
因為這是我們第一次提及 Nginx 的“調試日志”,是以有必要先簡單介紹一下它的啟用方法。調試日志預設是禁用的,因為它會引入比較大的運作時開銷,讓 Nginx 伺服器顯著變慢。一般我們需要重新編譯和構造 Nginx 可執行檔案,并且在調用 Nginx 源碼包提供的 <code>./configure</code> 腳本時傳入 <code>--with-debug</code> 指令行選項。例如我們下載下傳完 Nginx 源碼包後在 Linux 或者 Mac OS X 等系統上建構時,典型的步驟是這樣的:
現在我們重新啟動 Nginx(注意,如果 Nginx 可執行檔案也被更新過,僅僅讓 Nginx 重新加載配置是不夠的,需要關閉再啟動 Nginx 主服務程序),然後再請求一下我們剛才那個示例接口:
現在可以檢查一下前面配置的 Nginx 錯誤日志檔案中的輸出。因為檔案中的輸出比較多(在我的機器上有 700 多行),是以不妨用 <code>grep</code> 指令在終端上過濾出我們感興趣的部分:
在我機器上的輸出是這個樣子的(為了友善呈現,這裡對 <code>grep</code> 指令的實際輸出作了一些簡單的編輯,略去了每一行的行首時間戳):
這兩行就對應我們例子中的配置語句
而接下來這兩行調試資訊
則對應配置語句
此時的輸出便符合那個問題示例的初衷了: