写入本地磁盘文件除了popen()系统调用以外没有更高效的方法?

132 views
Skip to first unread message

黄欢

unread,
May 24, 2012, 12:37:28 PM5/24/12
to open...@googlegroups.com
hi all, 第一次提问,略腼腆 :)

我正使用ngx+lua开发一个静态文件分发系统,有一个主要的功能就是向 upstream 请求数据(tar包二进制流),然后解压在本地磁盘上作为cache,然后输出给访问者。

测试了很多种方案,发现最快速方案居然是直接系统调用,实现代码类似如下:

 
local buff = cloud.get(cachekey) --fetch sth. from upstream                                                          
buff = ngx.decode_base64(ngx.unescape_uri(buff))                                            
local tmpath = os.tmpname()                                                                
local file = io.open(tmpath, 'w')                                                          
file:write(buff)                                                                           
io.close(file)                                                                             
                                                                                           
-- expand cache                                                                            
os.exec(string.format("mkdir -p '%s'; tar xf '%s' -C '%s'", file_base, tmpath, file_base))

os.exec 实际上使用了 popen() 做系统调用,感觉这样实现不是特别稳定(实际上也是,error_log中偶尔会有wait_pid failed)

向大家请教一下有没有更好的方法?


To English users,  this post is asking a question about the performance of file-system i/o in ngx_lua.

Thanks,

Wendal Chen

unread,
May 24, 2012, 3:18:40 PM5/24/12
to open...@googlegroups.com
我也在使用类似的解决方法, 但你说的 " 不是特别稳定" ,我觉得只是os.execute执行得太快而已, 下一个周期到来的时候, 子进程已经执行完毕,所以wait pid failed




--
Wendal Chen
GuangDong China

Anfernee Gui

unread,
May 24, 2012, 8:57:37 PM5/24/12
to open...@googlegroups.com
不是很了解python,但你应该是说反了,应该是popen调用了exec家族。

- anfernee

2012/5/25 Wendal Chen <wenda...@gmail.com>



--
Best Regards,
Yongkun

Anfernee Gui

unread,
May 24, 2012, 8:58:54 PM5/24/12
to open...@googlegroups.com
sorry, it's lua. ignore me. 

2012/5/25 Anfernee Gui <anfern...@gmail.com>



--
Best Regards,
Yongkun

pengqi

unread,
May 24, 2012, 9:51:50 PM5/24/12
to open...@googlegroups.com
调用os.execute实际上开销很大,而且可能会阻塞当前的worker,如果系统压力稍大,这样的做法实在不妥。最好采用lua的第3方库非阻塞的来做。
error log中的wait_pid failed在这种情况下是很正常的, os.execute实际上是调用c的system()函数,该函数实际上会fork一个进程来做shell,然后会阻塞式waitpid到这个子进程结束,当该子进程结束会给该worker发SIGCHLD,该worker对应的信号处理函数中会掉用waitpid来回收,但是实际上system()中已经显示的用waitpid回收掉了,所以该worker信号处理函数的waitpid回收会失败,所以在error log中会写一条日志。
Jinglong
Software Engineer
Server Platforms Team at Taobao

boin - U know the Rules...

unread,
May 24, 2012, 10:10:55 PM5/24/12
to open...@googlegroups.com
Thanks Pengqi,解惑了:)

那现在问题似乎已经进化成了寻找一个lua非阻塞的文件io方案,不知道大家有无推荐呢?

Simon

unread,
May 25, 2012, 2:56:47 AM5/25/12
to openresty
没有,呵呵,以前讨论过

我觉得用io库应该够用了,控制每次写入的块大小,不要一次写太多数据导致进程阻塞时间过长


On 5月25日, 上午10时10分, "boin - U know the Rules..." <mcfeeb...@gmail.com>
wrote:


> Thanks Pengqi,解惑了:)
>
> 那现在问题似乎已经进化成了寻找一个lua非阻塞的文件io方案,不知道大家有无推荐呢?
>

> 在 2012年5月25日 上午9:51,pengqi <fengm...@gmail.com>写道:
>
>
>
>
>
>
>
> > 调用os.execute实际上开销很大,而且可能会阻塞当前的worker,如果系统压力稍大,这样的做法实在不妥。最好采用lua的第3方库非阻塞的来做。
> > error log中的wait_pid failed在这种情况下是很正常的, os.execute实际上是调用c的system()函数,该函数实际上会fork一个进程来做shell,然后会阻塞式waitpid到这个子进程结束,当该子进程结束会给该worker发SIGCHLD,该worker对应的信号处理函数中会掉用waitpid来回收,但是实际上system()中已经显示的用waitpid回收掉了,所以该worker信号处理函数的waitpid回收会失败,所以在error
> > log中会写一条日志。
>

> > 在 2012年5月25日 上午8:58,Anfernee Gui <anfernee....@gmail.com>写道:
>
> > sorry, it's lua. ignore me.
>

> >> 2012/5/25 Anfernee Gui <anfernee....@gmail.com>


>
> >>> 不是很了解python,但你应该是说反了,应该是popen调用了exec家族。
>
> >>> - anfernee
>

> >>> 2012/5/25 Wendal Chen <wendal1...@gmail.com>


>
> >>>> 我也在使用类似的解决方法, 但你说的 " 不是特别稳定" ,我觉得只是os.execute执行得太快而已, 下一个周期到来的时候,
> >>>> 子进程已经执行完毕,所以wait pid failed
>

> >>>>> 建议: 提问的智慧http://wiki.woodpecker.org.cn/moin/AskForHelp


> >>>>> 教程:http://agentzh.org/misc/nginx/agentzh-nginx-tutorials-zhcn.html
>
> >>>> --
> >>>> Wendal Chen
> >>>> GuangDong China
>
> >>>> --
> >>>> 邮件自: 列表"openresty",专用于技术讨论!
> >>>> 发言: 请发邮件到 open...@googlegroups.com
> >>>> 退订: 请发邮件至 openresty+...@googlegroups.com
> >>>> 详情:http://groups.google.com/group/openresty
> >>>> 官网:http://openresty.org/
> >>>> 仓库:https://github.com/agentzh/ngx_openresty

> >>>> 建议: 提问的智慧http://wiki.woodpecker.org.cn/moin/AskForHelp


> >>>> 教程:http://agentzh.org/misc/nginx/agentzh-nginx-tutorials-zhcn.html
>
> >>> --
> >>> Best Regards,
> >>> Yongkun
>
> >> --
> >> Best Regards,
> >> Yongkun
>
> >> --
> >> 邮件自: 列表"openresty",专用于技术讨论!
> >> 发言: 请发邮件到 open...@googlegroups.com
> >> 退订: 请发邮件至 openresty+...@googlegroups.com
> >> 详情:http://groups.google.com/group/openresty
> >> 官网:http://openresty.org/
> >> 仓库:https://github.com/agentzh/ngx_openresty

> >> 建议: 提问的智慧http://wiki.woodpecker.org.cn/moin/AskForHelp

kindy

unread,
May 25, 2012, 3:11:37 AM5/25/12
to open...@googlegroups.com
如果 .tar 包都很小,就引入 lua 能处理 tar 的扩展,直接操作就好了。
目录操作之类可以使用 luaposix 搞。
io操作这种必不可免的事情,就尽快的做完就好。

如果是比较大的 .tar 包,就做独立的任务系统吧,nginx 只负责创建 tar 文件(然后通知任务系统后sleep),任务系统来轮询或者被通知去解压 tar,完毕后让 nginx 继续就好。

nginx 和 任务系统的交互,可以让 nginx 有限的 sleep 轮询,或者借助 redis 的 brpoplpush (http://redis.io/commands/brpoplpush)。


2012/5/25 黄欢 <mcfe...@gmail.com>

--
邮件自: 列表“openresty”,专用于技术讨论!
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
详情: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
Reply all
Reply to author
Forward
0 new messages