<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    Nginx 配置指令的執行順序(九)

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

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

     

        當 Nginx 在 find-config 階段成功匹配了一個 location 配置塊后,會立即打印一條調試信息到錯誤日志文件中。我們來看這樣的一個例子:

        location /hello {
            echo "hello world";
        }

    如果啟用了 Nginx 的“調試日志”,那么當請求 /hello 接口時,便可以在 error.log 文件中過濾出下面這一行信息:

        $ grep 'using config' logs/error.log
        [debug] 84579#0: *1 using configuration "/hello"

    我們有意省略了信息行首的時間戳,以便放在這里。

     

        運行在 find-config 階段之后的便是我們的老朋友 rewrite 階段。由于 Nginx 已經在 find-config 階段完成了當前請求與 location 的配對,所以從 rewrite 階段開始,location 配置塊中的指令便可以產生作用。前面已經介紹過,當 ngx_rewrite 模塊的指令用于 location 塊中時,便是運行在這個 rewrite 階段。另外,ngx_set_misc 模塊的指令也是如此,還有 ngx_lua 模塊的 set_by_lua 指令和 rewrite_by_lua 指令也不例外。

     

        rewrite 階段再往后便是所謂的 post-rewrite 階段。這個階段也像 find-config 階段那樣不接受 Nginx 模塊注冊處理程序,而是由 Nginx 核心完成 rewrite 階段所要求的“內部跳轉”操作(如果 rewrite 階段有此要求的話)。先前在 (二) 中已經介紹過了“內部跳轉”的概念,同時演示了如何通過 echo_exec 指令或者 rewrite 指令來發起“內部跳轉”。由于 echo_exec 指令運行在 content 階段,與這里討論的 post-rewrite 階段無關,于是我們感興趣的便只剩下運行在 rewrite 階段的 rewrite 指令。回顧一下 (二) 中演示過的這個例子:

        server {
            listen 8080;
     
            location /foo {
                set $a hello;
                rewrite ^ /bar;
            }
     
            location /bar {
                echo "a = [$a]";
            }
        }

    這里在 location /foo 中通過 rewrite 指令把當前請求的 URI 無條件地改寫為 /bar,同時發起一個“內部跳轉”,最終跳進了 location /bar 中。這里比較有趣的地方是“內部跳轉”的工作原理。“內部跳轉”本質上其實就是把當前的請求處理階段強行倒退到 find-config 階段,以便重新進行請求 URI 與 location 配置塊的配對。比如上例中,運行在 rewrite 階段的 rewrite 指令就讓當前請求的處理階段倒退回了 find-config 階段。由于此時當前請求的 URI 已經被 rewrite 指令修改為了 /bar,所以這一次換成了 location /bar 與當前請求相關聯,然后再接著從 rewrite 階段往下執行。

     

        不過這里更有趣的地方是,倒退回 find-config 階段的動作并不是發生在 rewrite 階段,而是發生在后面的 post-rewrite 階段。上例中的 rewrite 指令只是簡單地指示 Nginx 有必要在 post-rewrite 階段發起“內部跳轉”。這個設計對于 Nginx 初學者來說,或許顯得有些古怪:“為什么不直接在 rewrite 指令執行時立即進行跳轉呢?”答案其實很簡單,那就是為了在最初匹配的 location 塊中支持多次反復地改寫 URI,例如:

        location /foo {
            rewrite ^ /bar;
            rewrite ^ /baz;
     
            echo foo;
        }
     
        location /bar {
            echo bar;
        }
     
        location /baz {
            echo baz;
        }

    這里在 location /foo 中連續把當前請求的 URI 改寫了兩遍:第一遍先無條件地改寫為 /bar,第二遍再無條件地改寫為 /baz. 而這兩條 rewrite 語句只會最終導致 post-rewrite 階段發生一次“內部跳轉”操作,從而不至于在第一次改寫 URI 時就直接跳離了當前的 location 而導致后面的 rewrite 語句沒有機會執行。請求/foo 接口的結果證實了這一點:

        $ curl localhost:8080/foo
        baz

    從輸出結果可以看到,上例確實成功地從 /foo 一步跳到了 /baz 中。如果啟用 Nginx “調試日志”的話,還可以從 find-config 階段生成的 locatin 塊的匹配信息中進一步證實這一點:

        $ grep 'using config' logs/error.log
        [debug] 89449#0: *1 using configuration "/foo"
        [debug] 89449#0: *1 using configuration "/baz"

    我們看到,對于該次請求,Nginx 一共只匹配過 /foo 和 /baz 這兩個 location,從而只發生過一次“內部跳轉”。

     

        當然,如果在 server 配置塊中直接使用 rewrite 配置指令對請求 URI 進行改寫,則不會涉及“內部跳轉”,因為此時 URI 改寫發生在 server-rewrite 階段,早于執行 location 配對的 find-config 階段。比如下面這個例子:

        server {
            listen 8080;
     
            rewrite ^/foo /bar;
     
            location /foo {
                echo foo;
            }
     
            location /bar {
                echo bar;
            }
        }

    這里,我們在 server-rewrite 階段就把那些以 /foo 起始的 URI 改寫為 /bar,而此時請求并沒有和任何location 相關聯,所以 Nginx 正常往下運行 find-config 階段,完成最終的 location 匹配。如果我們請求上例中的 /foo 接口,那么 location /foo 根本就沒有機會匹配,因為在第一次(也是唯一的一次)運行find-config 階段時,當前請求的 URI 已經被改寫為 /bar,從而只會匹配 location /bar. 實際請求的輸出正是如此:

        $ curl localhost:8080/foo
        bar

    Nginx “調試日志”可以再一次佐證我們的結論:

        $ grep 'using config' logs/error.log
        [debug] 92693#0: *1 using configuration "/bar"

    可以看到,Nginx 總共只進行過一次 location 匹配,并無“內部跳轉”發生。

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全