openresty - 基础及运行机制

2018-07-31 16:29:39

局部模块在同一个worker中是共享的

在同一个 worker 中,使用 local 修饰的模块代码和数据只会被加载一次,该模块下的数据在同一个 worker 下的所有请求共享,但是全局的却不是(也就是不加 local 修饰),那是由于一个请求一个协程的设计原则。

location /lua {
    content_by_lua_block {
        local mydata = require "mydata"
        ngx.say(mydata.get_age("dog"))
    }
}

当第一次请求 /lua 时,当前 worker 会加载缓存该模块,接下来所有到 /lua 的请求都会使用预先加载的数据,这也是 openresty 高性能的原因所在。

一定要注意,数据在同一个 worker 下共享,换句话说,启动 nginx 如果有多个 worker 进程,它们之间是不共享数据的,如果想多个 worker 进程之间共享数据,可以利用如下计数:

1.使用 ngx.shared.DICT api(接下来会讲到)
2.使用第三方的如 memcached、redis、mysql等

变量作用域

在大多数情况下,变量声明的时候带上 local 标识符,声明为局部变量。

原因是,在设计上,全局变量是跟请求相关联的,也就是说一个请求一个全局环境。如果一个变量声明为全局,那么它的生命周期会跟随一个请求的建立到一个请求的消亡,当一个请求结束时,该变量会被清除,而且在全局环境中搜寻开销比在局部里大。静止使用全局变量的原因如下:

1.在高并发的情况下可能会有意想不到情况发生
2.在全局环境里搜索变量开销很大,影响性能
3.不易于调试

openresty 作者如此强调,所以就不用多想,所有变量都声明为局部即可,比如

 -- 避免
 foo = 123
 -- 推荐
 local foo = 123

 -- 避免
 function foo() return 123 end
 -- 推荐
 local function foo() return 123 end

但是有时候,我们开发一个大的项目,总有大意的时候,如果不小心把变量声明为全局了,我们也很难发现。

作者早就帮我们想到了,我们可以使用 lua-releng 工具来检测,它是用 perl 语言写的,一般的 linux 环境都是自带 perl 解释器的,所以直接下载下来在要检测的代码目录运行即可。

个别子请求不能配合其他模块指令

ngx.location.capture 和 ngx.location.capture_multi 子请求指令请求的 location 不能包含以下指令 add_before_body、add_after_body、auth_request、echo_location、echo_location_async、echo_subrequest、echo_subrequest_async。

 location /foo {
     content_by_lua_block {
         res = ngx.location.capture("/bar")
     }
 }
 location /bar {
     echo_location /blah;
 }
 location /blah {
     echo "Success!";
 }
curl -i http://localhost/foo  #失败

介入 nginx 各个阶段

读过 nginx 源码的或者是熟悉nginx运行原理的朋友应该知道,nginx 分为很多阶段,比如重写阶段、访问控制阶段、内容阶段、日志阶段。ngx_lua 的功能指令基本上于各个阶段对应,可以执行对应的业务逻辑,关系图大致如下


备注

1.测试环境centos7 64位,openresty 版本为 1.13.6.2。
2..原文地址http://www.freecls.com/a/2712/ed


©著作权归作者所有
收藏
推荐阅读
简介
天降大任于斯人也,必先苦其心志。