Hello!
2012/10/25 龚开晖:
> Hi, 春哥,我最近在试用nginx lua模块的时候发现,如果在Lua脚本中输出大量的内容,进程会进入无法响应的状态。
>
> 在N次后调用ngx.flush(true),就不会有问题。但是这样似乎不太优雅可靠。
>
> local all_keys = server:keys("*")
>
> for i, k in ipairs(all_keys) do
>
> ngx.say(k)
>
> local t = i % 10000
>
> if t == 0 then
>
> ngx.flush(true)
>
> end
>
> end
>
ngx.print(), ngx.say() 和 ngx.flush() 都是高代价操作,一般都会调用整个 nginx
输出过滤器链,经常也会产生一次 writev 这样的系统调用(何时产生系统调用取决于 postpone_output 配置指令的设置
[1],默认 1460 字节)。
如果你有大量的输出,建议自己在 Lua 层面进行缓冲,然后以较大块的数据调用 ngx.print()/ngx.say()
输出,并周期性地通过 ngx.flush(true) 来确保对于慢连接,不会产生数据在 nginx
一侧的积压(这同时也是对客户端慢连接攻击的有效防护)。
另外,当进程进入不响应的状态时,建议使用 flamegraph 这样的工具 [2] 画出 CPU
时间分布图以确认热点所在(当然,更直接的做法是使用 pstack 和 strace 这样的工具)。我估计在你这里是因为过度频繁地调用
ngx.say() 所致。
同时抄送给 openresty 邮件列表:https://groups.google.com/group/openresty
(国内访问可能需要翻墙)。希望你也加入此列表并在那里讨论这样的问题 :)
Best regards,
-agentzh
[1] http://nginx.org/en/docs/http/ngx_http_core_module.html#postpone_output
[2] http://dtrace.org/blogs/brendan/2011/12/16/flame-graphs/ 与
https://groups.google.com/forum/?fromgroups=#!topic/openresty/u-puKWWONMk