OpenResty 1.21 做的网关,worker 进程 RSS 从六十 M 一路涨到八百 M,运维一周重启一次才稳住,limit_req 用的共享字典还时不时报 no memory。

一开始怀疑是「worker 之间不共享普通变量,为了绕开这点又去开更大的共享字典」,查了一圈,方向不对。

原因不止一个,得分开看。lua 代码把响应体整段塞进局部 table,请求结束前不释放,堆只涨不降。少数情况下是lua_shared_dict 只给了 10m,限流与缓存抢同一块空间,写不进去就报错。

不容易想到的是,日志与统计模块把每条请求的明细累积在内存里,只在重启时才清空。

上来先看哪个 worker 占得最多

ps -o pid,rss,cmd -C nginx --sort=rss | tail -3

然后确认共享字典都给了多大

grep -rn 'lua_shared_dict' /usr/local/openresty/nginx/conf/nginx.conf

接着把限流用的字典单独放大

sed -i 's/lua_shared_dict cache 10m/lua_shared_dict cache 128m/' /usr/local/openresty/nginx/conf/nginx.conf && nginx -t && nginx -s reload

等前面都确认过,再排查哪些 lua 逻辑在缓存大对象

grep -rn 'ngx.shared\|set(' /usr/local/openresty/nginx/conf | head -20

改完先别撤,确认这几项。worker 的 RSS 稳定在两百 M 以内且一周内不再单调上涨,共享字典的错误消失,网关键值与延迟保持平稳。

提醒一点。共享字典是按 worker 各自映射同一块内存,容量要按峰值算;lua 里缓存大对象前先想清楚失效策略。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189