<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系統、金蝶與條碼系統對接、用友與條碼系統對接

    我們前面已經知道,當 set 指令用在 location 配置塊中時,都是在當前請求的 rewrite 階段運行的。事實上,在此上下文中,ngx_rewrite 模塊中的幾乎全部指令,都運行在 rewrite 階段,包括 Nginx 變量漫談(二) 中介紹過的 rewrite 指令。不過,值得一提的是,當這些指令使用在 server 配置塊中時,則會運行在一個我們尚未提及的更早的處理階段,server-rewrite 階段。

     

        Nginx 變量漫談(二) 中介紹過的 ngx_set_misc 模塊的 set_unescape_uri 指令同樣也運行在 rewrite階段。特別地,ngx_set_misc 模塊的指令還可以和 ngx_rewrite 的指令混合在一起依次執行。我們來看這樣的一個例子:

        location /test {
            set $a "hello%20world";
            set_unescape_uri $b $a;
            set $c "$b!";
     
            echo $c;
        }

    訪問這個接口可以得到:

        $ curl 'http://localhost:8080/test'
        hello world!

    我們看到,set_unescape_uri 語句前后的 set 語句都按書寫時的順序一前一后地執行了。

     

        為了進一步確認這一點,我們不妨再檢查一下 Nginx 的“調試日志”(如果你還不清楚如何開啟“調試日志”的話,可以參考 (一) 中的步驟):

        grep -E 'http script (value|copy|set)' t/servroot/logs/error.log

    過濾出來的調試日志信息如下所示:

        [debug] 11167#0: *1 http script value: "hello%20world"
        [debug] 11167#0: *1 http script set $a
        [debug] 11167#0: *1 http script value (post filter): "hello world"
        [debug] 11167#0: *1 http script set $b
        [debug] 11167#0: *1 http script copy: "!"
        [debug] 11167#0: *1 http script set $c

    開頭的兩行信息

        [debug] 11167#0: *1 http script value: "hello%20world"
        [debug] 11167#0: *1 http script set $a

    就對應我們的配置語句

        set $a "hello%20world";

    而接下來的兩行

        [debug] 11167#0: *1 http script value (post filter): "hello world"
        [debug] 11167#0: *1 http script set $b

    則對應配置語句

        set_unescape_uri $b $a;

    我們看到第一行信息與  這個標記,而且最后顯示出 URI 解碼操作確實如我們期望的那樣工作了,即 "hello%20world" 在這里被成功解碼為 "hello world".

     

        而最后兩行調試信息

        [debug] 11167#0: *1 http script copy: "!"
        [debug] 11167#0: *1 http script set $c

    則對應最后一條 set 語句:

        set $c "$b!";

    注意,因為這條指令在為 $c 變量賦值時使用了“變量插值”功能,所以第一行調試信息是以 http script copy 起始的,后面則是拼接到最終取值的字符串常量 "!".

     

        把這些調試信息聯系起來看,我們不難發現,這些配置指令的實際執行順序是:

        set $a "hello%20world";
        set_unescape_uri $b $a;
        set $c "$b!";

    這與它們在配置文件中的書寫順序完全一致。

     

        我們在 Nginx 變量漫談(七) 中初識了第三方模塊 ngx_lua,它提供的 set_by_lua 配置指令也和ngx_set_misc 模塊的指令一樣,可以和 ngx_rewrite 模塊的指令混合使用。set_by_lua 指令支持通過一小段用戶 Lua 代碼來計算出一個結果,然后賦給指定的 Nginx 變量。和 set 指令相似,set_by_lua 指令也有自動創建不存在的 Nginx 變量的功能。

     

        下面我們就來看一個 set_by_lua 指令與 set 指令混合使用的例子:

        location /test {
            set $a 32;
            set $b 56;
            set_by_lua $c "return ngx.var.a + ngx.var.b";
            set $equation "$a + $b = $c";
     
            echo $equation;
        }

    這里我們先將 $a 和 $b 變量分別初始化為 32 和 56,然后利用 set_by_lua 指令內聯一行我們自己指定的 Lua 代碼,計算出 Nginx 變量 $a 和 $b 的“代數和”(sum),并賦給變量 $c,接著利用“變量插值”功能,把變量 $a、 $b 和 $c 的值拼接成一個字符串形式的等式,賦予變量 $equation,最后再用 echo 指令輸出 $equation 的值。

     

        這個例子值得注意的地方是:首先,我們在 Lua 代碼中是通過 ngx.var.VARIABLE 接口來讀取 Nginx 變量$VARIABLE 的;其次,因為 Nginx 變量的值只有字符串這一種類型,所以在 Lua 代碼里讀取 ngx.var.a 和ngx.var.b 時得到的其實都是 Lua 字符串類型的值 "32" 和 "56";接著,我們對兩個字符串作加法運算會觸發 Lua 對加數進行自動類型轉換(Lua 會把兩個加數先轉換為數值類型再求和);然后,我們在 Lua 代碼中把最終結果通過 return 語句返回給外面的 Nginx 變量 $c;最后,ngx_lua 模塊在給 $c 實際賦值之前,也會把return 語句返回的數值類型的結果,也就是 Lua 加法計算得出的“和”,自動轉換為字符串(這同樣是因為 Nginx 變量的值只能是字符串)。

     

        這個例子的實際運行結果符合我們的期望:

        $ curl 'http://localhost:8080/test'
        32 + 56 = 88

    于是這驗證了 set_by_lua 指令確實也可以和 set 這樣的 ngx_rewrite 模塊提供的指令混合在一起工作。

     

        還有不少第三方模塊,例如 Nginx 變量漫談(八) 中介紹過的 ngx_array_var 以及后面即將接觸到的用于加解密用戶會話(session)的 ngx_encrypted_session,也都可以和 ngx_rewrite 模塊的指令無縫混合工作。

     

        標準 ngx_rewrite 模塊的應用是如此廣泛,所以能夠和它的配置指令混合使用的第三方模塊是幸運的。事實上,上面提到的這些第三方模塊都采用了特殊的技術,將它們自己的配置指令“注入”到了 ngx_rewrite 模塊的指令序列中(它們都借助了 Marcus Clyne 編寫的第三方模塊 ngx_devel_kit)。換句話說,更多常規的在 Nginx 的 rewrite 階段注冊和運行指令的第三方模塊就沒那么幸運了。這些“常規模塊”的指令雖然也運行在rewrite 階段,但其配置指令和 ngx_rewrite 模塊(以及同一階段內的其他模塊)都是分開獨立執行的。在運行時,不同模塊的配置指令集之間的先后順序一般是不確定的(嚴格來說,一般是由模塊的加載順序決定的,但也有例外的情況)。比如 A 和 B 兩個模塊都在 rewrite 階段運行指令,于是要么是 A 模塊的所有指令全部執行完再執行 B 模塊的那些指令,要么就是反過來,把 B 的指令全部執行完,再去運行 A 的指令。除非模塊的文檔中有明確的交待,否則用戶一般不應編寫依賴于此種不確定順序的配置。

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