nginx利用ctx实现数据共享、修改上下文功能
环境: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表可以用来存储基于请求的Lua环境数据,其生存周期与当前请求相同(类似Nginx变量)。
参考下面例子,
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)
}
}
访问GET/test输出
79
也就是说,ngx.ctx.foo条目跨越一个请求的rewrite(重写),access(访问),和content(内容)各处理阶段保持一致。
每个请求,包括子请求,都有一份自己的ngx.ctx表。例如:
location/sub{
content_by_lua_block{
ngx.say("subpre:",ngx.ctx.blah)
ngx.ctx.blah=32
ngx.say("subpost:",ngx.ctx.blah)
}
}
location/main{
content_by_lua_block{
ngx.ctx.blah=73
ngx.say("mainpre:",ngx.ctx.blah)
localres=ngx.location.capture("/sub")
ngx.print(res.body)
ngx.say("mainpost:",ngx.ctx.blah)
}
}
访问GET/main输出
mainpre:73
subpre:nil
subpost:32
mainpost:73
这里,在子请求中修改ngx.ctx.blah条目并不影响父请求中的同名条目,因为它们各自维护不同版本的ngx.ctx.blah。
内部重定向将摧毁原始请求中的ngx.ctx数据(如果有),新请求将会有一个空白的ngx.ctx表。例如,
location/new{
content_by_lua_block{
ngx.say(ngx.ctx.foo)
}
}
location/orig{
content_by_lua_block{
ngx.ctx.foo="hello"
ngx.exec("/new")
}
}
访问GET/orig将输出
nil
而不是原始的"hello"值。
任意数据值,包括Lua闭包与嵌套表,都可以被插入这个“魔法”表,也允许注册自定义元方法。
也可以将ngx.ctx覆盖为一个新Lua表,例如,
ngx.ctx={foo=32,bar=54}
当用在init_worker_by_lua*环境中,这个表与当前Lua句柄生命周期相同。
ngx.ctx表查询需要相对昂贵的元方法调用,这比通过用户自己的函数参数直接传递基于请求的数据要慢得多。所以不要为了节约用户函数参数而滥用此API,因为它可能对性能有明显影响。
而且由于元方法“魔法”,不要在lua模块级别试图使用"local"级别的ngx.ctx,例如worker-leveldatasharing。下面示例是糟糕的:
--mymodule.lua
local_M={}
--下面一行的ngx.ctx是属于单个请求的,但ctx变量是在Lua模块级别
--并且属于单个worker的。
localctx=ngx.ctx function_M.main() ctx.foo="bar" end return_M
应使用下面方式替代:
--mymodule.lua
local_M={}
function_M.main(ctx)
ctx.foo="bar"
end
return_M
就是说,调用者对ctx表调用应通过函数传参方式完成。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。