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