openresty開發系列33--openresty執行流程之2重寫賦值階段

openresty開發系列33--openresty執行流程之2重寫賦值階段

一)重寫賦值階段

1)set_by_lua

語法:set_by_lua $res <lua-script-str> [$arg1 $arg2 …]
語境:server、server if、location、location if
階段:rewrite

設置nginx變量,咱們用的set指令即便配合if指令也很難實現負責的賦值邏輯;

傳入參數到指定的lua腳本代碼中執行,並獲得返回值到res中。
<lua-script-str>中的代碼可使從ngx.arg表中取得輸入參數(順序索引從1開始)。

這個指令是爲了執行短時間、快速運行的代碼由於運行過程當中nginx的事件處理循環是處於阻塞狀態的。
耗費時間的代碼應該被避免。
禁止在這個階段使用下面的API:
一、output api(ngx.say和ngx.send_headers);
二、control api(ngx.exit);
三、subrequest api(ngx.location.capture和ngx.location.capture_multi);
四、cosocket api(ngx.socket.tcp和ngx.req.socket);
五、sleep api(ngx.sleep)

a、nginx.conf配置文件

location /lua {
    set $jump "1";
    echo $jump;
}

set 命令對變量進行賦值,但有些場景的賦值業務比較複雜,須要用到lua腳本
因此用到set_by_lua

b、補充知識點:

ngx.var.arg與ngx.req.get_uri_args的區別,都是可以獲取請求參數

ngx.var.arg_xx與ngx.req.get_uri_args["xx"]二者都是爲了獲取請求uri中的參數
例如 http://pureage.info?strider=1
爲了獲取輸入參數strider,如下兩種方法均可以:

local strider = ngx.var.arg_strider

local strider = ngx.req.get_uri_args["strider"]

差異在於,當請求uri中有多個同名參數時,ngx.var.arg_xx的作法是取第一個出現的值
ngx.req_get_uri_args["xx"]的作法是返回一個table,該table裏存放了該參數的全部值

例如,當請求uri爲:http://pureage.info?strider=1&strider=2&strider=3&strider=4時

ngx.var.arg_strider的值爲"1",而ngx.req.get_uri_args["strider"]的值爲table ["1", "2", "3", "4"]。
所以,ngx.req.get_uri_args屬於ngx.var.arg_的加強。

-------------------------------
案例需求:書店網站改造把以前的skuid爲8位商品,請求到之前的頁面,爲9位的請求到新的頁面
書的商品詳情頁進行了改造,美化了一下;上線了時候,不要一會兒切換美化頁面;;作AB概念
把新錄入的書的商品 採用 新的商品詳情頁,以前維護的書的商品詳情頁 用老的頁面

之前書的id 爲8位,新的書id爲9位

    root /data/www/html;

        location /book {

                set_by_lua $to_type '
                        local skuid = ngx.var.arg_skuid
                        ngx.log(ngx.ERR,"skuid=",skuid)
                        local r = ngx.re.match(skuid, "^[0-9]{8}$")
                        local k = ngx.re.match(skuid, "^[0-9]{9}$")
                        if r then
                                return "1"
                        end;
                        if k then
                                return "2"
                        end;
                ';

                if ($to_type = "1") {
                        echo "skuid爲8位";
                        proxy_pass http://127.0.0.1/old_book/$arg_skuid.html;
                }
                if ($to_type = "2") {
                        echo "skuid爲9位";
                        proxy_pass http://127.0.0.1/new_book/$arg_skuid.html;
                }

        }


# 具體的網頁內容
[root@node5 data]# tree /data/www/html/
/data/www/html/
├── new_book
│   └── 123456789.html
└── old_book
    └── 12345678.html

2 directories, 2 files
[root@node5 data]# cat /data/www/html/old_book/12345678.html
<h1>old book</h1>
[root@node5 data]# cat /data/www/html/new_book/123456789.html
<h1>new book</h1>


# 測試訪問:http://10.11.0.215/book?skuid=123456789
會跳轉到new_book/123456789.html

訪問:http://10.11.0.215/book?skuid=12345678
會跳轉到new_book/12345678.html

=======================================

2)set_by_lua_file

語法set_by_lua_file $var lua_file arg1 arg2...;

在lua代碼中能夠實現全部複雜的邏輯,可是要執行速度很快,不要阻塞;

location /lua_set_1 {
    default_type "text/html";
    set_by_lua_file $num /usr/local/luajit/test_set_1.lua;
    echo $num;
}

2.一、test_set_1.lua

local uri_args = ngx.req.get_uri_args()
local i = uri_args["i"] or 0
local j = uri_args["j"] or 0

return i + j

獲得請求參數進行相加而後返回。

訪問如http://192.168.31.138/lua_set_1?i=1&j=10進行測試。 若是咱們用純set指令是沒法實現的。

3)注意,這個指令只能一次寫出一個nginx變量,可是使用ngx.var接口能夠解決這個問題:

location /foo {
    set $diff '';
    set_by_lua $sum '
        local a = 32
        local b = 56
        ngx.var.diff = a - b; --寫入$diff中
        return a + b;  --返回到$sum中
    ';
    echo "sum = $sum, diff = $diff";
}html

相關文章
相關標籤/搜索