Nginx Lua API 学习

一、Nginx Lua API 的两个标准库: ngx 和 ndk

1. 在 nginx.conf 文件中,所有的 *_by_lua, *_by_lua_block 和 _by_lua_file 都被看做是一个通向 Lua API 的入口。Nginx Lua API 中的函数只能在上述配置指令中(_by_lua, *_by_lua_block 和 *_by_lua_file)运行。
2. Nginx Lua API 通过向 Lua 提供 ngx 和 ndk 两个标准库来实现 Lua 对 Nginx Lua API 的调用。这两个标准库一般情况下,在上述配置指令中(*_by_lua, *_by_lua_block 和 *_by_lua_file)总是可用的,也可以将这两个标准库集成到任意的Lua模块中。也可用在外部 Lua 模块中,使用 local ngx = require "ngx" 和 local ndk = require "ndk" 来手动引入

二、总是在 Lua 代码中使用 Nginx Lua API 来完成网络请求和磁盘IO

1. 使用 Nginx Lua API 来完成网络请求,否则 Nginx 的事件轮询将被阻塞,导致性能急剧下降。
2. 小量的磁盘IO可用使用 Lua 自身的IO库来完成,但应该尽量避免对大文件的读和写导致Nginx进程阻塞。
3. 将网络请求和磁盘IO委托给Nginx的子请求将明显提高nginx性能。

三、ngx.var

1. 可用通过 value = ngx.var.*** 来获取变量,通过 ngx.var.*** = 123 来设置变量的值。但 ngx.var 的变量只能先声明后使用。
2. 一些系统变量,如:query_string,http_NAME,只是可读的。
3. 可用通过 ngx.var[1], ngx.var[2] .. 来获取正则表达式的 12
4. 手动将 ngx.var.*** = nil 设置为空,将会删除这个变量
5. 每次读 ngx.var.*** 变量时,nginx会在只读一次的内存块中分配一块内存来保存这个变量,并且在读操作完成后,销毁它。因此,在反复读某个 ngx.var.*** 变量时,最好先将变量保存到 lua 变量中。同时,如果为了避免在同一次请求过程中的临时内存泄露,也可以将 ngx.var.*** 保存到 ngx.ctx 中。
6. 未声明的 ngx.var.*** 变量默认是 nil,在 lua 中是 "" 空字符串。尽量避免对未申明的变量的使用,因为比较耗性能。

四、常量

1. Core Constants
  • ngx.OK: 0
  • ngx.ERROR: -1
  • ngx.AGAIN: -2
  • ngx.DONE: -4
  • ngx.DECLINED: -5
  • ngx.null
2. HTTP Method Constants 作为 ngx.location.capturengx.location.capture_multi 的参数
  • ngx.HTTP_GET
  • ngx.HTTP_HEAD
  • ngx.HTTP_PUT
  • ngx.HTTP_POST
  • ngx.HTTP_DELETE
  • ngx.HTTP_OPTIONS
  • ngx.HTTP_MKCOL
  • ngx.HTTP_COPY
  • ngx.HTTP_MOVE
  • ngx.HTTP_PROPFIND
  • ngx.HTTP_PROPPATCH
  • ngx.HTTP_LOCK
  • ngx.HTTP_UNLOCK
  • ngx.HTTP_PATCH
  • ngx.HTTP_TRACE
3. HTTP Status Constants
image.png
4. Nginx 日志等级常量
  • ngx.STDERR
  • ngx.EMERG
  • ngx.ALERT
  • ngx.CRIT
  • ngx.ERR
  • ngx.WARN
  • ngx.NOTICE
  • ngx.INFO
  • ngx.DEBUG

五、print 函数

print 函数用于:以 nginx.NOTICE 级别向 error.log 文件写入日志,等同与: ngx.log(ngx.NOTICE, ...)

六、ngx.ctx 上下文数组

1. ngx.ctx 是一个 table,它的生命周期和本次请求的生命周期一样,可以存储一些本次请求过程中的数据。
2. 每一个请求,包含子请求,都有各自独立的 ngx.ctx 互不干扰。即:主请求的 ngx.ctx.var_ctx 和 ngx.location.capture() 出来的子请求中的 ngx.ctx.var_ctx 互不干扰。
3. 主请求中的 ngx.ctx 数据并不延续到内部重定向的请求中。即:在主请求中设置 ngx.ctx.var_master=value,然后 ngx.exec() 后,内部重定向的请求中,local var_master=ngx.ctx.var_master 将为 nil。
4. 可以使用 lua table 对 ngx.ctx 进行初始化,如: ngx.ctx = {a=1,b=2}。如果在 init_worker_by_lua 中这样做,将使其在整个请求的 Lua 处理过程中都有效。
5. 相比在每次请求中传递自定义函数参数和使用 ngx.ctx,ngx.ctx 中查询相当耗费性能,滥用 ngx.ctx 将对性能产生很大影响。

七、ngx.location.capture

1. res = ngx.location.capture(uri, options?),产生一个指定uri的同步并非阻塞的子请求
2. 子请求模仿了 http 请求,但并不会进行 HTTP/TCP 通信,它只是在 C 语言层面上工作。子请求和 ngx.redirect 和 ngx.exec 完全不同。子请求的返回值将保存在内存中,对于庞大的返回值,需要流式处理。
3. ngx.location.capture 的返回值对象 res 有4个键值:
  • res.status, 保存了子请求的状态码
  • res.header, 按返回顺序,以二位数组的方式,保存的返回的头信息
  • res.body, 保存了子请求的返回内容,可能会由于内容过长被截断。数据被截断的原因是子请求中出现了一些解决不了的错误,比如:在返回数据的过程中,子请求提前断开了链接,或者子请求在请求其他服务时遭遇了超时。
  • res.truncated, 表明子请求是否被截断。
4.ngx.location.capture 可选参数 table:
  • method:指定子请求的请求方法。默认 ngx.HTTP_GET
  • body:字符串类型的请求体
  • args:URI 查询参数
  • ctx:指定子请求使用的上下文环境。在当前轻轻中,使用变量作为子请求的 ctx 时,若子请求通过 ngx.ctx.***=aaa 修改了 ctx,修改将作用到当前请求被传递至 ctx 作为子请求上下文环境的变量。
  • vars:指定子请求的 ngx.var
  • copy_all_vars:是否复制当前请求的 ngx.var 变量到子请求中(子请求对变量的修改并不会影响到当前请求)
  • share_all_vars:是否在当前请求和子请求间共享 ngx.var 变量(子请求对变量的修改将影响到当前请求)。开启本参数将使调试等变得很困难,慎重开启。默认 false。与 copy_all_vars 同时使用时,share_all_vars 优先生效。与 copy_all_vars 和 vars 同时使用时,vars 优先生效。
  • always_forward_body:是否将当前请求的请求体作为子请求的请求体
5. 子请求默认使用和当前请求一样的请求头信息
6. POST 和 PUT 类型的子请求,当未设置 body 参数且 always_forward_body=false 时,子请求将继承当前请求的 body 信息
7. 在 1.1.x 版本之前,一个请求最多可以有 50 个子请求,在 1.1.x 之后的版本,一个请求最多可以有 200 个子请求。可以修改 nginx/src/http/ngx_http_request.h 中的 NGX_HTTP_MAX_SUBREQUESTS 来修改这个限制

八、ngx.location.capture_multi

1. res1, res2, ... = ngx.location.capture_multi({ {uri, options?}, {uri, options?}, ... }), 并行地发出多个子请求,且返回顺序和发出顺序一致。
2. 直到所有的子请求都返回后,才会返回。且总延迟依赖与子请求中最大的延迟。
3. 当子请求数量不确定时,可以 local resps = { ngx.location.capture_multi(reqs) } 的方式对结果进行 for i, resp in ipairs(resps) do 处理。

九、ngx.status

1. 可以在当前请求输出响应头信息之前,查看或者设置当前请求的返回状态码。在输入响应头信息之后设置 ngx.status 没有任何意义且会报错。
2. ngx.status = ngx.HTTP_CREATED,设置当前请求的响应状态码
3. status = ngx.status,查看当前请求的响应状态码

十、ngx.header.*** 查看或设置当前请求的返回头信息

1. ngx.header.*** = VALUE,设置返回头信息
2. value = ngx.header.***,查看返回头信息
3. 默认情况下,头信息下的 _ 将被替换成 -,即:content_type 会被改写成 content-type,可以用过关闭 lua_transform_underscores_in_response_headers 来禁用此功能。响应头信息是大小写敏感的。
4. ngx.header["***"] = nil,将删除之前设定的 *** 返回头信息。
5. 在发送响应头之后,无论使用 ngx.send_headers 或者 ngx.header.*** = VALUE 都将产生错误,并记录到 error.log 中。
6. ngx.header 并不是一个常规的 Lua table,不能使用 ipairs 来遍历它。但可以使用 ngx.req.get_headers 来获取一个可遍历的常规 Lua table、

十一、ngx.reps.get_headers 和 ngx.req.get_headers

1. headers = ngx.resp.get_headers(max_headers?, raw?),返回一个包含当前请求所有响应头信息的常规 Lua table。
2. headers = ngx.req.get_headers(),返回一个包含当前请求所有请求头信息的常规 Lua table。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容