OpenResty 中 lua 脚本的使用

OpenResty 用 lua-nginx-module 解释 lua 脚本,lua 语言自身的用法见 Lua编程速查手册(常用操作),openresty 提供的 lua 能力(譬如定义的变量、提供的函数等)见 openresty/lua-nginx-module

OpenResty 执行 Lua 脚本

OpenResty 支持的开发语言是 lua,lua 脚本可以用两种方式运行:

第一种方式,直接写在配置文件中,openresty 加载运行:

$ cd 01-hello-world
$ openresty -p `pwd` -c nginx.conf

这种方式启动了 openresty 服务,访问 openresty 时触发配置中的 lua 脚本的运行:

$ curl 127.0.0.1:6699/
HelloWorld

第二种方式,用 resty 命令直接执行 lua 脚本:

$ cd 02-hello-world
$ resty hello.lua
hello world

lua_module 的几个执行阶段

lua_module 定义了很多的指令,lua module directives,其中有一些指令是类似于 server、location 的块指令,它们的作用顺序如下:

lua_module 指令的的作用顺序

用下面的配置观察这些指令的执行顺序,03-nginx-lua-module/nginx.conf:

worker_processes  1;             #nginx worker 数量
error_log logs/error.log info;   #指定错误日志文件路径
events {
  worker_connections 256;
}

http {
  server {
    #监听端口,若你的6699端口已经被占用,则需要修改
    listen 6699;
    location / {
        set_by_lua_block $a {
            ngx.log(ngx.INFO, "set_by_lua*")
        }
        rewrite_by_lua_block {
            ngx.log(ngx.INFO, "rewrite_by_lua*")
        }
        access_by_lua_block {
            ngx.log(ngx.INFO, "access_by_lua*")
        }
        content_by_lua_block {
            ngx.log(ngx.INFO, "content_by_lua*")
        }
        header_filter_by_lua_block {
            ngx.log(ngx.INFO, "header_filter_by_lua*")
        }
        body_filter_by_lua_block {
            ngx.log(ngx.INFO, "body_filter_by_lua*")
        }
        log_by_lua_block {
            ngx.log(ngx.INFO, "log_by_lua*")
        }
    }
  }
}

执行时打印的日志:

2019/10/23 15:40:34 [info] 65194#3586531: *1 [lua] set_by_lua:2: set_by_lua*, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "127.0.0.1:6699"
2019/10/23 15:40:34 [info] 65194#3586531: *1 [lua] rewrite_by_lua(nginx.conf:17):2: rewrite_by_lua*, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "127.0.0.1:6699"
2019/10/23 15:40:34 [info] 65194#3586531: *1 [lua] access_by_lua(nginx.conf:20):2: access_by_lua*, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "127.0.0.1:6699"
2019/10/23 15:40:34 [info] 65194#3586531: *1 [lua] content_by_lua(nginx.conf:23):2: content_by_lua*, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "127.0.0.1:6699"
2019/10/23 15:40:34 [info] 65194#3586531: *1 [lua] header_filter_by_lua:2: header_filter_by_lua*, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "127.0.0.1:6699"
2019/10/23 15:40:34 [info] 65194#3586531: *1 [lua] body_filter_by_lua:2: body_filter_by_lua*, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "127.0.0.1:6699"
2019/10/23 15:40:34 [info] 65194#3586531: *1 [lua] log_by_lua(nginx.conf:32):2: log_by_lua* while logging request, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "127.0.0.1:6699"
2019/10/23 15:40:34 [info] 65194#3586531: *1 kevent() reported that client 127.0.0.1 closed keepalive connection

与 nginx 内置变量的交互

nginx 有很多 内置变量,在 lua 脚本中通过 ngx.var.VARIABLE 获取这些变量。

有一些 nginx 的变量值可以用 lua 修改,大部分是不可以修改的。

修改不能修改的变量时会报错,例如:

lua entry thread aborted: runtime error: ... variable "request_uri" not changeable

与 nginx 共享内存的交互

ngx.shared.DICT 获取用 ua_shared_dict 创建的共享内存。

当前请求的上下文

ngx.ctx 中存放当前请求的上下文,贯穿所有处理阶段:

 location /test {
     rewrite_by_lua_block {
         ngx.ctx.foo = 76
     }
     access_by_lua_block {
         ngx.ctx.foo = ngx.ctx.foo + 3
     }
     content_by_lua_block {
         ngx.say(ngx.ctx.foo)
     }
 }

常用 lua 数据结构

Lua的基本数据类型

参考

  1. 李佶澳的博客