• 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日志收集分析

  • 相关阅读:
    图的概述
    "《算法导论》之‘排序’":线性时间排序
    “《算法导论》之‘查找’”:散列表
    如何使用VS2013本地C++单元测试框架
    “《算法导论》之‘查找’”:顺序查找和二分查找
    查找算法概述
    第二部分 位运算符、赋值运算符、三元及一元运算符和语句分类
    LINQ 的查询_联表、分组、排序
    第二部分 关系与比较运算符 、 自增与自减运算符、条件逻辑运算符
    LINQ to Sql系列一 增,删,改
  • 原文地址:https://www.cnblogs.com/reblue520/p/11446487.html
Copyright © 2020-2023  润新知