非阻塞的 pipe 实现 (Was Re: [openresty] 关于openresty 调用io.popen在压力测试中报错的问题)

195 views
Skip to first unread message

agentzh

unread,
Mar 22, 2013, 2:45:52 PM3/22/13
to open...@googlegroups.com
Hello!

2013/3/21 junwei shi:
> 春哥,最近我在学习ngx_lua
> 我也想通过实际的开发来加深对ngx_lua的理解,所以我有兴趣抽时间来实现一个非阻塞的popen

好极了,欢迎贡献补丁。

> 我现在大概的思路是:
> 1.重新实现io.popen,把打开的文件指针对应句柄设置为非阻塞
> 2.重新实现io.read.
> 如果文件不可读(返回EAGAIN/EWOULDBLOCK等),把相应的回调函数注册到nginx的事件模型里,并调用lua_yield放弃执行权。
> 3.回调函数被回调:读取内容,并放到lua的栈里,并重新唤醒lua协程。(如cosocket类似的思想)
>

或许在步骤 1 中就可以把对应 pipe 的 fd 注册到 nginx 事件模型中,而不是等到第一次调用
io.read(),这样如果有错误事件也可以提早进行处理,从而提早释放相关的资源。

> 由于popen会fork一个新的进程,所以大量并发调用非阻塞版本的popen,也不是一个好主意,所以计划会引入一个类似队列的缓冲区的实现;如超过最大的进程数,后续的popen调用会放到队列里,如果步骤3的callback完成了一个读操作以后,则检查队列是否为空,然后.....
>

对于 pipe 的并发控制,可以维护一个简单的排队队列,队列里面放置对应 io.pipe() 调用的 Lua 协程的
ngx_http_lua_co_ctx_t 指针就可以了。

其实,这种针对后端连接(或者说上游连接)的并发控制可以考虑做成更加通用的形式,这样 cosocket 等其他东西也可以享受同一套机制 ;)

Best regards,
-agentzh
Reply all
Reply to author
Forward
0 new messages