Nginx 的 worker_processes 配置决定 worker 进程数量,每个进程拥有独立 Lua VM 和全局环境 _G,变量天然按 worker 隔离;跨 worker 共享数据必须使用 lua_shared_dict 声明的共享内存。

Nginx 的 worker_processes 配置决定启动多少个 worker 进程,每个进程完全独立运行——拥有各自的内存空间、连接表、定时器和 Lua 虚拟机(Lua VM)。这意味着:Lua 全局变量在不同 worker 中互不相通,也永远不会共享。
Lua 全局变量天然按 worker 隔离
OpenResty 中,每个 worker 进程初始化时会创建一个独立的 Lua VM。所有请求协程都运行在这个 VM 内,共用该 VM 的全局环境 _G。但这个 _G 仅限于当前 worker 进程内有效:
-
init_by_lua* 阶段定义的变量,只在本 worker 启动时执行一次,作用域是本 worker 的
_G -
access_by_lua_block 或 content_by_lua_block 中直接写
a = 1,创建的是本协程局部变量(因 OpenResty 默认启用了lua_code_cache on且做了沙箱隔离);若未加local又非 init 阶段,实际会写入本 worker 的_G,但仍无法被其他 worker 读到 - 多个 worker 同时处理请求,各自维护一套
_G副本,修改彼此毫无影响
真正需要跨 worker 共享数据时,必须用 shared dict
如果业务要求统计全站状态码、限流计数、黑白名单同步等,靠“全局变量”行不通——必须显式使用共享内存机制:
- 在
http块中声明:lua_shared_dict status_stats 10m; - 在 Lua 代码中通过
ngx.shared.status_stats访问,调用incr()、get()等原子方法 - 所有 worker 进程操作的是同一块预分配的共享内存区域,底层由 Nginx 的 slab 分配器 + 自旋锁/原子指令保障安全
- 避免在 handler 中 new 对象或动态构造 key,防止内存泄漏或 key 泄漏
模块变量 ≠ 全局变量,但它在 worker 内部是共享的
使用 require 加载的 Lua 模块(如 mylib.lua),其顶层定义的变量(即使没加 local)属于模块自身,而非 _G。这些变量在同一个 worker 内被所有协程复用:
- 适合存放只读配置、预编译正则、连接池对象等
- 若需在模块中维护可变状态(如计数器),必须配合
ngx.shared_dict,不能依赖模块变量本身 - 模块变量不会跨 worker 复制,每个 worker 加载模块时各自初始化一份
常见误区与规避方式
以下做法看似方便,实则不可靠:
- 在
access_by_lua_block里写counter = (counter or 0) + 1→ 实际是 worker 内局部统计,重启后清零,多 worker 下数据割裂 - 用
init_worker_by_lua_block启动定时器轮询本地变量 → 各自查各自的副本,无法反映全局真实值 - 把共享逻辑封装进模块,却忘了内部仍用普通变量 → 模块只是语法包装,不解决进程隔离本质
- 误以为
worker_processes auto会自动协调数据 → 它只控制进程数量,对数据一致性零影响


















