1.
local class_mt = {
-- to prevent use of casual module global variables
__newindex = function (table, key, val)
error('attempt to write to undeclared variable "' .. key .. '"')
end
}
setmetatable(_M, class_mt)
This will guarantee that local variables in the Lua module functions are all declared with the local
keyword, otherwise a runtime exception will be thrown. It prevents undesirable race conditions while accessing such variables. See Data Sharing within an Nginx Worker for the reasons behind this.
1.对上面的描述有点不理解:添加这段代码的意义是为了防止module里定义的function里的变量不带local声明(如果都带上local,上面的代码是否非必要了?),导致在一个worker进程内,它以一个全局变量的身份存在的情况?但是为什么会导致内存泄漏?是因为可能存在msg = msg + “xxxx"这样的情况,累积导致内存泄漏?
2.http://wiki.nginx.org/HttpLuaModule#Data_Sharing_within_an_Nginx_Worker 里用了一个错误的指令:content_lua_by_lua?
3.看agentzh最新的lua-resty-*模块,module("resty.xxx", package.seeall) 改成 module(...),而且下面的代码也被替换了,可以说说主要的原因么?
getmetatable(resty.xxx).__newindex = function (table, key, val)
error('attempt to write to undeclared variable "' .. key .. '": '
.. debug.traceback())
end
谢谢
On Wednesday, November 28, 2012 1:02:44 PM UTC+8, agentzh wrote:
Hello!2012/11/27 杨虎:
> 我现在尝试使用了下nginx lua模块编写业务模块,感觉挺爽的,能用同步的方式编写非阻塞的代码,感觉挺好的,对人类是一个伟大的贡献。。。
>
多谢鼓励! :)
> 我的业务代码模型是这样的,通过nginx tcp
> sock链接一个后端的一个路由服务(自定义的协议,不是http协议),该服务返回一个url后,将sock
> 通过setkeepalive保存到连接池。然后通过pass_proxy访问该url。
>
[...]
> call_ra就是访问后端的服务,其响应时间不是很快。hap模块的编写方式参考你写的mysql的模块。压力运行一段时候停止后发觉nginx的每个worker的rss都差不多在700多m了。导致OOM。。。
>
多谢你的报告!只是我想先问几个问题:
1. 你使用的是什么版本的 ngx_lua 模块?或者你使用的是某个版本的 openresty 软件包?请确保你使用的是最新版本 :)
2. 你使用的是最新的 LuaJIT 2.0.0 正式版吗?较老一些的 LuaJIT 版本的内存分配器存在已知的内存泄漏 bug.
3. 你是在 Linux x86_64 上面?
4. 你能通过下面这个接口检查一下 Lua 的 GC 实现分配了多少空间?
location = /gc {
content_by_lua '
collectgarbage()
ngx.say(string.format("Worker %d: GC size: %.3f KB",
ngx.var.pid, collectgarbage("count"))) ';
}
}
5. 你能否使用 Nginx Systemtap Toolkit 中的 ngx-active-reqs, ngx-shm,
ngx-cycle-pool, 和 ngx-leaked-pools 这几个工具分析一下你存在内存泄漏的 nginx worker
进程内部的内存分配(不包含 Lua GC 的部分)?
https://github.com/agentzh/nginx-systemtap-toolkit#ngx-active-reqs
6. 你是否方便提供一个最小化的可以复现问题的完整示例,以便我可以在我本地复现你看到的泄漏?这样我可以以最快的速度修正问题(如果有的话)。
>
> 在本机通过valgrind跑了下结果如附件。
>
你提供的 valgrind 报告中未见到确定的内存泄漏位置。
> 第一次使用lua写程序,是不是写的lua发生了内存泄漏?
>
常见的 Lua 程序的泄漏是由于把数据不断累积到自定义的 Lua module 级别的变量中去,而 Lua module 级别的数据在
worker 进程中是共享和持久的,见这里:
http://wiki.nginx.org/HttpLuaModule#Data_Sharing_within_an_Nginx_Worker
http://wiki.nginx.org/HttpLuaModule#Lua_Variable_Scope
我明天再写一个 Lua 工具动态分析你的 nginx worker 进程中 Lua GC 的内存分配细节(就像 Nginx
SystemTap Toolkit 里的那些分析 Nginx 内存分配细节的工具那样)。
同时抄送给 openresty 中文邮件列表:https://groups.google.com/group/openresty
这样其他用户也可以看到我们这里的讨论。同时也欢迎你加入此列表 :)
Thanks!
-agentzh