openresty开发系列36--openresty执行流程之6日志模块处理阶段
openresty開發系列36--openresty執行流程之6日志模塊處理階段
一)header_filter_by_lua ?
語法:header_filter_by_lua <lua-script-str>
語境:http,server,location,location if
階段:output-header-filter
一般用來設置cookie和headers,在該階段不能使用如下幾個API:
1、output API(ngx.say和ngx.send_headers)
2、control API(ngx.exit和ngx.exec)
3、subrequest API(ngx.location.capture和ngx.location.capture_multi)
4、cosocket API(ngx.socket.tcp和ngx.req.socket)
案例一:
location / {
??? header_filter_by_lua 'ngx.header.Foo = "blah"';
??? echo "Hello World!";
}
案例二:
http { ?
?
??? log_format? main? '$msec $status $request $request_time ' ?
????????????????????? '$http_referer $remote_addr [ $time_local ] ' ?
????????????????????? '$upstream_response_time $host $bytes_sent ' ?
????????????????????? '$request_length $upstream_addr'; ?
?
??? access_log? logs/access.log main buffer=32k flush=1s; ?
?
??? upstream remote_world { ?
??????? server 127.0.0.1:8080; ?
??? } ?
?
??? server { ?
??????? listen 80; ?
?
??????? location /exec { ?
??????????? content_by_lua ' ?
??????????????? local cjson = require "cjson" ?
??????????????? local headers = { ?
??????????????????? ["Etag"] = "662222165e216225df78fbbd47c9333", ?
??????????????????? ["Last-Modified"] = "Sat, 24 July 2019 16:58:22 GMT", ?
??????????????? } ?
??????????????? ngx.var.my_headers = cjson.encode(headers) ?
??????????????? ngx.var.my_upstream = "remote_world" ?
??????????????? ngx.var.my_uri = "/world" ?
??????????????? ngx.exec("/upstream") ?
??????????? '; ?
??????? } ?
?
??????? location /upstream { ?
??????????? internal; ?
?
??????????? set $my_headers $my_headers; ?
??????????? set $my_upstream $my_upstream; ?
??????????? set $my_uri $my_uri; ?
??????????? proxy_pass http://$my_upstream$my_uri; ?
?
??????????? header_filter_by_lua ' ?
??????????????? local cjson = require "cjson" ?
??????????????? headers = cjson.decode(ngx.var.my_headers) ?
??????????????? for k, v in pairs(headers) do ?
??????????????????? ngx.header[k] = v ?
??????????????? end ?
??????????? '; ?
??????? } ?
??? } ?
?
?
??? server { ?
??????? listen 8080; ?
?
??????? location /world { ?
??????????? echo "hello world"; ?
??????? } ?
??? } ?
} ?
二)body_filter_by_lua
語法:body_filter_by_lua <lua-script-str>
語境:http,server,location,location if
階段:output-body-filter
輸入的數據時通過ngx.arg[1](作為lua的string值),通過ngx.arg[2]這個bool類型表示響應數據流的結尾。
這個指令可以用來篡改http的響應正文的;會調用幾次
在該階段不能利用如下幾個API:
1、output API(ngx.say和ngx.send_headers)
2、control API(ngx.exit和ngx.exec)
3、subrequest API(ngx.location.capture和ngx.location.capture_multi)
4、cosocket API(ngx.socket.tcp和ngx.req.socket)
輸入的數據時通過ngx.arg[1],通過ngx.arg[2]這個bool范例暗示響應數據流的末了。
基于這個原因,’eof’只是nginx的鏈接緩沖區的last_buf(對主requests)或last_in_chain(對subrequests)的標志。
運行以下呼吁可以當即終止運行接下來的lua代碼:
return ngx.ERROR
這會將響應體截斷導致無效的響應。lua代碼可以通過修改ngx.arg[1]的內容將數據傳輸到下游的
nginx output body filter階段的其它模塊中去。譬喻,將response body中的小寫字母舉辦反轉,我們可以這么寫:
案例一
location /t {
??? echo hello world12;
??? echo hi yile;
??? body_filter_by_lua '
??????? ngx.log(ngx.ERR,"ngx.arg[1]=",ngx.arg[1]," arg[2]=",ngx.arg[2])
??????? ngx.arg[1] = string.upper(ngx.arg[1])
??? ';
}
盡管只有兩個 echo,但是 body_filter_by_lua* 會被調用三次!
第三次調用的時候,ngx.arg[1] 為空字符串,而 ngx.arg[2] 為 true。
這是因為,Nginx 的 upstream 相關模塊,以及 OpenResty 的 content_by_lua,
會單獨發送一個設置了 last_buf 的空 buffer,來表示流的結束。這算是一個約定俗成的慣例,所以有必要在運行相關邏輯之前,
檢查 ngx.arg[1] 是否為空。當然反過來不一定成立,ngx.arg[2] == true 并不代表 ngx.arg[1] 一定為空。
案例二
location /t {
??? echo hello world;
??? echo hiya globe;
??? body_filter_by_lua '
??????? ngx.log(ngx.ERR,"ngx.arg[1]=",ngx.arg[1]," arg[2]=",ngx.arg[2])
??????? local chunk = ngx.arg[1]
??????? if string.match(chunk, "hello") then
??????????? ngx.arg[2] = true? -- new eof
??????????? return
??????? end
??????? ngx.arg[1] = nil
??? ';
}
這是因為,當body filter看到了一塊包括”hello“的字符塊后當即將”eof“標志配置為了true,
從而導致響應被截斷了但仍然是有效的回覆。
三)log_by_lua,log_by_lua_file
在log階段指定的lua日志,并不會替換access log,而是在那之后調用。
在該階段不能利用如下幾個API:
1、output API(ngx.say和ngx.send_headers)
2、control API(ngx.exit和ngx.exec)
3、subrequest API(ngx.location.capture和ngx.location.capture_multi)
4、cosocket API(ngx.socket.tcp和ngx.req.socket)
可以利用此階段,把日志統一收集到日志服務器中
location / {
??? echo "Hello World!";
??? log_by_lua_block {
??????? ngx.log(ngx.ERR,msg)
??? }
}
elk日志收集分析
轉載于:https://www.cnblogs.com/reblue520/p/11446487.html
總結
以上是生活随笔為你收集整理的openresty开发系列36--openresty执行流程之6日志模块处理阶段的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: openresty开发系列35--ope
- 下一篇: Hadoop实例之利用MapReduce