天天看点

【精选】Nginx模块Lua-Nginx-Module学习笔记(一)Nginx Lua API 接口详解CDN 反向代理LiveNode节点,通过Lua脚本操作Redis数据库实现转发

  各种* _by_lua,* _by_lua_block和* _by_lua_file配置指令用作nginx.conf文件中Lua API的网关。 下面描述的Nginx Lua API只能在这些配置指令的上下文中运行的用户Lua代码中调用。API以两个标准软件包ngx和ndk的形式暴露给Lua。 这些软件包位于ngx_lua中的默认全局范围内,并且始终可在ngx_lua指令中使用。

这些包可以像这样引入外部Lua模块:

强烈建议使用package.seeall标志,因为其各种不良的副作用。也可以直接要求外部Lua模块中的包:

  v0.2.1rc19版本中引入了需要这些软件包的能力。

  用户代码中的网络I / O操作应该只通过Nginx Lua API调用来完成,因为Nginx事件循环可能被阻塞,否则性能会明显下降。 磁盘操作与相对少量的数据可以使用标准的Lua io库,但巨大的文件读写应尽可能避免,因为他们可能会显着阻止Nginx进程。 强烈建议将所有网络和磁盘I / O操作委派给Nginx的子请求(通过ngx.location.capture方法等),以获得最佳性能。

语法:val = ngx.arg [index]

上下文:set_by_lua *,body_filter_by_lua *

描述:当在set_by_lua *指令的上下文中使用时,此表是只读的,并保存config指令的输入参数:

这里是一个例子

CURL 运行输出

写出88,32和56的和。

  当在body_filter_by_lua *的上下文中使用此表时,第一个元素将输入数据块保存到输出过滤器代码,第二个元素保存指示整个输出数据流结束的“eof”标志的布尔标志。

  传递给下游Nginx输出过滤器的数据块和“eof”标志也可以通过将值直接分配给相应的表元素来覆盖。 当将nil或空Lua字符串值设置为ngx.arg [1]时,根本不会将数据块传递到下游Nginx输出过滤器。

  ngx.null常量是一个NULL light用户数据,通常用于在Lua表等中表示nil值,类似于lua-cjson库的cjson.null常量。 这个常数首先在v0.5.0rc5版本中引入。

语法:ngx.var.VAR_NAME

上下文:set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*

读取和写入Nginx变量值

注意,只有已经定义的nginx变量可以写入。 例如:

  也就是说,nginx变量不能在运行中创建。一些特殊的nginx变量,如$ args和$ limit_rate可以分配一个值,许多其他变量不是,如$ query_string,$ arg_PARAMETER和$ http_NAME。通过写入ngx.var [1],ngx.var [2],ngx.var [3]等,也可以通过此接口读取Nginx正则表达式组捕获变量$ 1,$ 2,$ 3等。将ngx.var.Foo设置为nil值将取消设置$ Foo Nginx变量。

  小心当从Nginx变量读取时,Nginx将在每个请求的内存池中分配内存,只有在请求终止时才释放内存。 因此,当您需要在Lua代码中重复读取Nginx变量时,将Nginx变量值缓存到您自己的Lua变量中,例如:

  以防止(临时)内存在当前请求的生存期内泄漏。 缓存结果的另一种方法是使用ngx.ctx表。未定义的NGINX变量评估为nil,而未初始化(但已定义)的NGINX变量将被评估为空的Lua字符串。此API需要相对昂贵的元方法调用,建议避免在热代码路径上使用它。

上下文: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, *log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*

待续.........

上下文: init_by_lua *,* set_by_lua,rewrite_by_lua *,* access_by_lua,content_by_lua *,* header_filter_by_lua,body_filter_by_lua *,* log_by_lua,ngx.timer *,* balancer_by_lua,ssl_certificate_by_lua *,* ssl_session_fetch_by_lua,ssl_session_store_by_lua *。

上下文: init_by_lua *,* init_worker_by_lua,set_by_lua *,* rewrite_by_lua,access_by_lua *,* content_by_lua,header_filter_by_lua *,* body_filter_by_lua,log_by_lua *,* ngx.timer,balancer_by_lua *,* ssl_certificate_by_lua,ssl_session_fetch_by_lua *,* ssl_session_store_by_lua。

语法: print(...)

上下文: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*

写参数值到nginx的<code>error.log</code>与文件<code>ngx.NOTICE</code>日志级别。它相当于

Lua的<code>nil</code>参数被接受,并导致文字<code>"nil"</code>字符串,而Lua的布尔导致文字<code>"true"</code>或<code>"false"</code>字符串。和<code>ngx.null</code>常数将产生<code>"null"</code>串输出。

  有一个硬编码<code>2048</code>在Nginx的核心错误信息的长度字节的限制。此限制包括尾随换行符和领先的时间戳。如果邮件的大小超出此限制,Nginx的将相应截断消息文本。这个限制可以通过编辑手动修改<code>NGX_MAX_ERROR_STR</code>的宏定义<code>src/core/ngx_log.h</code>在Nginx的源代码树文件。

上下文: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*

这个表可以被用来存储每个请求的Lua上下文数据,并具有使用寿命相同当前请求(与Nginx的变量)。考虑下面的例子,

然后<code>GET /test</code>将产生的输出:79

即,<code>ngx.ctx.foo</code>条目横跨重写,访问和请求的内容相存在。每一项要求,其中包括子请求,有它自己的表的副本。例如:

然后<code>GET /main</code>会给输出:

在此,改性<code>ngx.ctx.blah</code>的子请求条目不会影响所述一个在父请求。这是因为他们有两个独立的版本<code>ngx.ctx.blah</code>。内部重定向会破坏原来的请求<code>ngx.ctx</code>数据(如果有的话)和新要求将有一个空<code>ngx.ctx</code>表。例如:

然后<code>GET /orig</code>会给:nil

而不是原来的<code>"hello"</code>值。任意的数据值,包括Lua的关闭和嵌套表,可以插入到这个“神奇”的表。它还允许自定义元方法的注册。覆盖<code>ngx.ctx</code>用一个新的Lua表也支持,例如:

改用以下内容:

也就是说,让调用者通过<code>ctx</code>表明确地通过一个函数的参数。

语法: res = ngx.location.capture(uri, options?)

上下文: rewrite_by_lua *,* access_by_lua,content_by_lua *

是一个同步非阻塞的NGINX子请求uri

NGINX的子请求提供了一个非常强大的方式去实现非阻塞的内部请求,或者其他的C模块,比如 ngx_proxy, ngx_fastcgi, ngx_memc, ngx_postgres, ngx_drizzle, 甚至ngx_lua自己等等。

当然,这些子请求仅仅是模拟HTTP请求,但是并没有额外的 HTTP/TCP,所有的进程都是C级别的

子请求完全不同与HTTP 301/302。

这里有个基本的例子:

返回与4插槽,一个Lua表:<code>res.status</code>,<code>res.header</code>,<code>res.body</code>,和<code>res.truncated</code>。

<code>res.status</code> 用于保存子请求响应的响应状态代码。

<code>res.header</code>持有子请求的响应头,这是一个正常的Lua表。对于多值响应头,该值是保存所有的顺序它们出现的值的Lua(阵列)表。例如,如果子请求响应报头包含以下几行:

返回一个LUA的TABLE,三个值(res.status, res.header, and res.body)。

res.header包含了所有的子请求的头的信息,它是一个普通的LUA TABLE。比如多个值的相应头,他们以数组的形式按照顺序返回出现。例如:子请求包含了如下信息:

然后<code>res.header["Set-Cookie"]</code>将被评估,以表中的值 <code>{"a=3", "foo=bar", "baz=blah"}</code>。

<code>  res.body</code>持有子请求的响应体数据,这些数据可能会被截断。你总是需要检查<code>res.truncated</code>布尔标志,看是否<code>res.body</code>包含截断数据。这里的数据截断只能由那些不可恢复的错误在你的子请求一样,远端中止在响应体数据流的中间,或当你的子请求接收从响应体数据的读取超时发生过早的连接的情况下造成的遥控器。URI查询串可以串联到的URI本身,例如:

像名为位置<code>@foo</code>不允许由于nginx的核心的限制。使用与组合正常位置<code>internal</code>指令准备仅供内部使用的位置。

可选选项表可以喂的第二个参数,它支持的选项:

<code>method</code> 指定子请求的请求方法,只接受常量一样<code>ngx.HTTP_POST</code>。

<code>body</code> 指定子请求的请求体(仅字符串值)。

<code>args</code> 指定子请求的URI查询参数(这两个字符串值和Lua表被接受)

<code>vars</code> 采取持有的值设置指定的Nginx变量在子请求作为此选项的值一个Lua表。此选项最初是在引进<code>v0.3.1rc31</code>发行。

<code>copy_all_vars</code> 指定是否在当前请求所讨论的子请求的所有的Nginx变量值复制。在子请求nginx的变量的修改将不会影响当前(父)的请求。此选项最初是在引进<code>v0.3.1rc31</code>发行。

<code>share_all_vars</code> 指定是否共享的子请求与当前(父)要求所有的Nginx变量。在子请求Nginx的变量的修改将影响当前(父)的请求。启用此选项可能会导致因不良副作用难以调试问题,被认为是不好的,有害的。只有启用该选项,当你完全知道自己在做什么。

发出一个POST子请求,例如,可以做如下:

看到比其他POST HTTP方法的常量方法。该<code>method</code>选项是<code>ngx.HTTP_GET</code>默认。

该<code>args</code>选项可以指定额外的URI参数,例如:

相当于

这在功能上等同于前面的例子。

该<code>share_all_vars</code>选项控制是否将当前请求和子请求之间共享nginx的变量。如果此选项设置为<code>true</code>,那么当前请求和相关的子请求将共享相同的Nginx变量的作用域。因此,通过一个子请求更改了Nginx的变量将影响到当前的请求。

应小心使用此选项,变量的作用域共享可以有意想不到的副作用。的<code>args</code>,<code>vars</code>或<code>copy_all_vars</code>选项通常优于代替。这个选项被设置为<code>false</code>默认

访问位置<code>/lua</code>给:

该<code>copy_all_vars</code>选项提供父请求的Nginx的变量的副本子请求时这样子请求发出。由这样子请求对这些变量所做的更改不会影响父请求或任何其他子请求共享父请求的变量。

请求<code>GET /lua</code>将给输出

请注意,如果两者<code>share_all_vars</code>并<code>copy_all_vars</code>都设置为true,则<code>share_all_vars</code>优先。

除了上述两个设置,有可能使用在子请求变量的值<code>vars</code>选项。这些变量的变量共享或复制已评估后设置,并且提供了对编码它们以URL参数,并在Nginx的配置文件反向转义它们传递特定值应用于一个子请求的更有效的方法:

访问<code>/lua</code>将产生的输出:

然后请求<code>GET /lua 输出:</code>

请求<code>GET /lua</code>产生的输出:bar

如果<code>body</code>没有指定选项,且<code>always_forward_body</code>选项为false(默认值),<code>POST</code>以及<code>PUT</code>子请求将继承父请求(如果有的话)的请求主体。

  上有可能为每一个主要请求并发子请求的数目的硬编码上限。在旧版本Nginx的,下限为<code>50</code>并行子请求,并在最近的版本中,Nginx的<code>1.1.x</code>开始,这是提高到<code>200</code>并发子请求。当超过此限制时,以下错误消息被添加到<code>error.log</code>文件中:

语法: secs = ngx.req.start_time()

上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*

语法:  num = ngx.req.http_version()

背景: set_by_lua *,* rewrite_by_lua,access_by_lua *,* content_by_lua,header_filter_by_lua *

返回当前请求作为Lua的数字的HTTP版本号。

当前可能的值是2.0,1.0,1.1和0.9。返回<code>nil</code>了无法识别的值。

语法:  str = ngx.req.raw_header(no_request_line?)

返回由Nginx的服务器接收到的原始原始的HTTP协议头。

默认情况下,请求行和尾随<code>CR LF</code>终止也将包括在内。例如,

给出这样的事情:

你可以指定可选的 <code>no_request_line</code>参数作为<code>true</code>排除从结果的请求行的值。例如

输出是这样的:

此方法不会在HTTP / 2请求工作尚未

URL访问地址:http://127.0.0.1/hls/4953.m3u8

nginx.conf 配置

 思路图片:

【精选】Nginx模块Lua-Nginx-Module学习笔记(一)Nginx Lua API 接口详解CDN 反向代理LiveNode节点,通过Lua脚本操作Redis数据库实现转发