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:
一、output API(ngx.say和ngx.send_headers)
二、control API(ngx.exit和ngx.exec)
三、subrequest API(ngx.location.capture和ngx.location.capture_multi)
四、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:
一、output API(ngx.say和ngx.send_headers)
二、control API(ngx.exit和ngx.exec)
三、subrequest API(ngx.location.capture和ngx.location.capture_multi)
四、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:
一、output API(ngx.say和ngx.send_headers)
二、control API(ngx.exit和ngx.exec)
三、subrequest API(ngx.location.capture和ngx.location.capture_multi)
四、cosocket API(ngx.socket.tcp和ngx.req.socket)

能夠利用此階段,把日誌統一收集到日誌服務器中

location / {
    echo "Hello World!";
    log_by_lua_block {
        ngx.log(ngx.ERR,msg)
    }
}
elk日誌收集分析

nginx

相關文章
相關標籤/搜索