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:
1、output api(ngx.say和ngx.send_headers);
2、control api(ngx.exit);
3、subrequest api(ngx.location.capture和ngx.location.capture_multi);
4、cosocket api(ngx.socket.tcp和ngx.req.socket);
5、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.1、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";
}
轉載于:https://www.cnblogs.com/reblue520/p/11446354.html
總結
以上是生活随笔為你收集整理的openresty开发系列33--openresty执行流程之2重写赋值阶段的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: openresty开发系列32--ope
- 下一篇: openresty开发系列33--ope