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

openresty开发系列36--openresty执行流程之6日志模块处理阶段的更多相关文章

  1. openresty开发系列35--openresty执行流程之5内容content阶段

    openresty开发系列35--openresty执行流程之5内容content阶段 content 阶段 ---init阶段---重写赋值---重写rewrite---access content ...

  2. openresty开发系列34--openresty执行流程之4访问阶段

    openresty开发系列34--openresty执行流程之4访问阶段 访问阶段 用途:访问权限限制 返回403 nginx:allow 允许,deny 禁止 allow ip:deny ip: 涉 ...

  3. openresty开发系列33--openresty执行流程之3重写rewrite和重定向

    openresty开发系列33--openresty执行流程之3重写rewrite和重定向 重写rewrite阶段 1)重定向2)内部,伪静态 先介绍一下if,rewrite指令 一)if指令语法:i ...

  4. openresty开发系列33--openresty执行流程之2重写赋值阶段

    openresty开发系列33--openresty执行流程之2重写赋值阶段 一)重写赋值阶段 1)set_by_lua 语法:set_by_lua $res <lua-script-str&g ...

  5. openresty开发系列32--openresty执行流程之1初始化阶段

    openresty开发系列32--openresty执行流程之初始化阶段 一)初始化阶段 1)init_by_lua   init_by_lua_block     init_by_lua_file语 ...

  6. openresty开发系列20--lua的时间操作

    openresty开发系列20--lua的时间操作 在 Lua 中,函数 time.date 和 difftime 提供了所有的日期和时间功能.在 OpenResty 的世界里,不推荐使用这里的标准时 ...

  7. openresty开发系列40--nginx+lua实现获取客户端ip所在的国家信息

    openresty开发系列40--nginx+lua实现获取客户端ip所在的国家信息 为了实现业务系统针对不同地区IP访问,展示包含不同地区信息的业务交互界面.很多情况下系统需要根据用户访问的IP信息 ...

  8. openresty开发系列38--通过Lua+Redis 实现动态封禁IP

    openresty开发系列38--通过Lua+Redis 实现动态封禁IP 一)需求背景为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单.对于黑名单之内的 IP ,拒绝 ...

  9. openresty开发系列37--nginx-lua-redis实现访问频率控制

    openresty开发系列37--nginx-lua-redis实现访问频率控制 一)需求背景 在高并发场景下为了防止某个访问ip访问的频率过高,有时候会需要控制用户的访问频次在openresty中, ...

随机推荐

  1. 浅谈Linux下傻瓜式磁盘分区工具cfdisk的使用

    对于新手来说,Linux环境下的磁盘分区可能还会存在一些困难.对于熟悉Linux的朋友来说,我们还有fdisk.parted(2TB以上的磁盘分区使用)等磁盘分区工具可以使用.在我们新增磁盘或者在原来 ...

  2. sklearn的class_weight设置为'balanced'的计算方法

    分类的时候,当不同类别的样本量差异很大时,很容易影响分类结果,因此要么每个类别的数据量大致相同,要么就要进行校正. sklearn的做法可以是加权,加权就要涉及到class_weight和sample ...

  3. 《TensorFlow2深度学习》学习笔记(二)手动搭建并测试简单神经网络(附mnist.npz下载方式)

    本实验使用了mnist.npz数据集,可以使用在线方式导入,但是我在下载过程中老是因为网络原因被打断,因此使用离线方式导入,离线包已传至github方便大家下载: https://github.com ...

  4. Kotlin中Range与异常体系剖析

    好用的集合扩展方法: 下面来看一下对于集合中好用的一些扩展方法,直接上代码: 如果我们想取出集合中的第一个值和最后一个值,用Java方式是get(0)和get(size-1),但是在Kotlin中提供 ...

  5. Product Oriented Recurrence(Codeforces Round #566 (Div. 2)E+矩阵快速幂+欧拉降幂)

    传送门 题目 \[ \begin{aligned} &f_n=c^{2*n-6}f_{n-1}f_{n-2}f_{n-3}&\\ \end{aligned} \] 思路 我们通过迭代发 ...

  6. 基于appium快速实现H5自动化测试

    一.下载Appium-Server及库文件 库文件:jar包:java-client-3.1.0.jar Appium-Server:Appium服务器: 注:Appium包含客户端和服务端,客户端就 ...

  7. Oracle 中select XX_id_seq.nextval from dual 什么意思呢?

    说明 今天看别人的代码 ,遇见了 一条sql    select ctg_fault_list_id_seq.nextval from dual  不懂意思,然后就研究了下 dual :是oracle ...

  8. 12.基于vue-router的案例

    案例分析 用到的路由技术要点: 路由的基础用法 嵌套路由 路由重定向 路由传参 编程式导航 根据项目的整体布局划分好组件结构,通过路由导航控制组件的显示 1.抽离并渲染 App根组件 2.将左侧菜 单 ...

  9. 转:MySQL到底能支持多大的数据量?

    MySQL到底能支持多大的数据量? MySQL是中小型网站普遍使用的数据库之一,然而,很多人并不清楚MySQL到底能支持多大的数据量,再加上某些国内CMS厂商把数据承载量的责任推给它,导致很多不了解M ...

  10. 关于Java的i++和++i的区别

    之前对于 i++ 和 ++i 的理解就是: int i=1,a=0; 1.i++ 先运算在赋值,例如 a=i++,先运算a=i,后运算i=i+1,所以结果是a==1 2.++i 先赋值在运算,例如 a ...