nginx 是多 worker 进程的模型,所以除了共享内存字典是所有 worker 进程共享之外,其他的数据都是每 worker 一份的,无论是在 init_by_lua 里面创建的全局变量,还是 Lua 模块里的状态变量。
在某个请求里面更新某个 Lua 变量,只是更新了当前处理这个请求的 nginx worker 进程里的状态,并不会影响其他的 worker 进程(除非只配置了一个 nginx worker)。
Lua VM 是每一个 nginx worker 进程一份。这些独立的 Lua VM 副本是从 nginx master 进程的 Lua VM 给 fork 出来的。而 init_by_lua 运行在 master 进程的 Lua VM 中,时间点发生在进程 fork 之前。
在共享内存字典中保存最新的数据,每个 worker 进程里通过 Lua 模块变量或者 init_by_lua 创建的全局变量
追踪
当前 worker 里实际使用的数据(worker需要不断同共享内存的数据进行比较并更新)。关于上述1、2、3、4点,更多请参考:
lua_code_cache的使用
- 关闭lua_code_cache, 则每一个请求都由一个独立的lua VM来处理。因此,通过A请求变更的lua数据(如模块变量),不会被B请求解析到,即使只配置了一个。
- 关闭lua_code_cache的好处,对于纯lua文件(不涉及nginx解析的),在不重启nginx的情况下也能立即生效。
- 启用lua_code_cache, 则同一个worker的所有请求共享一个lua VM的数据。因此,由该worker处理的A请求变更了lua数据(如模块变量),则会被同一个worker处理的B请求访问到。
- 生产环境强烈建议启用lua_code_cache,否则会带来较大的性能损失。
- 更多参考 这里
关于lua变量共享问题
- 尽量不使用全局变量
- 如果要使用,使用模块变量
- 如果模块变量无法满足,使用共享内存或者分布式缓存
- 更多参考 lua-variable-scope、变量的共享范围
- Data Sharing within an Nginx Worker
- data-sharing-in-openresty
不应使用模块级的局部变量以及模块属性,存放任何请求级的数据。否则在 luacodecache 开启时,会造成请求间相互影响和数据竞争,产生不可预知的异常状况。
1 | 关于变量共享的一个最小化配置: |