请教 lua-ngxin-module里tcpsock:connect无法非阻塞

244 views
Skip to first unread message

尹子铭

unread,
Apr 17, 2016, 11:16:41 PM4/17/16
to open...@googlegroups.com
 场景:nginx接收client发送的一个请求,会将其解析并生成多个新请求,并将每个新请求分别发送给多个上游server。解析及发送新请求均用lua实现
    目前用lua-ngxin-module的API  connect()向上游server建连时,如果有多台server建连超时,则所有超时时间会累加并反映到前端响应中,代码如下:
        for i = 1, num do    --num为上游server个数
            local tcp = ngx.socket.tcp()
            tcp:settimeout(3000)    --设置3秒超时
            res, err = tcp:connect(servers[i], 80)    --server[i]为每个上游server
        end
    如果有2台上游server建连超时,那返回给前端client的响应将延迟 3 * 2 = 6秒。之前看到网上对API  connect()的说明,是非阻塞工作的,但从这里的现象感觉是阻塞的。当有多台上游server建连超时,对前端原始请求会造成很大影响。
    而C代码里的非阻塞方式:调用connect(),设置o_noblock并把socket插入epoll监听队列,是不会出现超时累加的情况的。

    另外lua-ngxin-module的API  connect()的第3参数options_table用法不明,不知能否改善这个超时累加问题?
    在lua-ngxin-module中没有类似epoll/select的API,请教各位大神,如何实现非阻塞建连?
    个人lua-ngxin-module版本为v0.9.4。
    
    最开始使用lua-resty-http的API  connect()也有同样的问题。

YuanSheng Wang

unread,
Apr 19, 2016, 10:23:07 AM4/19/16
to open...@googlegroups.com
2016-04-18 11:16 GMT+08:00 尹子铭 <cello...@gmail.com>:
 场景:nginx接收client发送的一个请求,会将其解析并生成多个新请求,并将每个新请求分别发送给多个上游server。解析及发送新请求均用lua实现
    目前用lua-ngxin-module的API  connect()向上游server建连时,如果有多台server建连超时,则所有超时时间会累加并反映到前端响应中,代码如下:
        for i = 1, num do    --num为上游server个数
            local tcp = ngx.socket.tcp()
            tcp:settimeout(3000)    --设置3秒超时
            res, err = tcp:connect(servers[i], 80)    --server[i]为每个上游server
        end

openresty 体系中的异步非阻塞,指的是所有网络操作,不会因为某个 connect、read、recieve 动作影响整个 ngx 的事件循环机制。比如下面两个例子,两个请求同时到服务端:

请求1 --> 后端 connect(耗时 3 秒) --> 应答 --> 结束

请求2 --> 后端 connect(耗时 3 秒) --> 应答 --> 结束

由于 connect 操作是异步执行的,当它发生阻塞的时候,是不会影响其他请求的任何网络动作。所以从两个请求送达到全部接收到结果,总耗时是 3 秒。

但是对于每个请求自身而言,他的超时等待是必须且必要的。

 
    如果有2台上游server建连超时,那返回给前端client的响应将延迟 3 * 2 = 6秒。之前看到网上对API  connect()的说明,是非阻塞工作的,但从这里的现象感觉是阻塞的。当有多台上游server建连超时,对前端原始请求会造成很大影响。
    而C代码里的非阻塞方式:调用connect(),设置o_noblock并把socket插入epoll监听队列,是不会出现超时累加的情况的。

    另外lua-ngxin-module的API  connect()的第3参数options_table用法不明,不知能否改善这个超时累加问题?
    在lua-ngxin-module中没有类似epoll/select的API,请教各位大神,如何实现非阻塞建连?
    个人lua-ngxin-module版本为v0.9.4。
    
    最开始使用lua-resty-http的API  connect()也有同样的问题。

--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html



--

YuanSheng Wang
---------------------------------------
OpenResty lover ^_^

violoncello

unread,
Apr 19, 2016, 10:46:07 PM4/19/16
to openresty
多谢Yuan Sheng大大的解答!!

之前我也是这么理解的,所以在循环里调用connect,期望能互不影响,非阻塞的发送多条新建请求。但是结果却是,产生这些新请求的原始请求的超时等待时间,是所有新请求的超时时间之和“3 * 2 = 6秒”,看起来就是循环里的connect是串行阻塞执行的。而所期望的非阻塞执行的结果,应该是原始请求仅仅超时3秒左右<一个新请求的超时时间>
 

violoncello

unread,
Apr 19, 2016, 10:49:34 PM4/19/16
to openresty
是不是需要用个类似epoll或者select的lua_nginx_module的API,和connect配套使用?就像C那样

DeJiang Zhu

unread,
Apr 20, 2016, 2:00:14 AM4/20/16
to open...@googlegroups.com
Hello

你可以用 ngx.thread.spawn 来并发

在 2016年4月20日 上午10:49,violoncello <cello...@gmail.com>写道:
是不是需要用个类似epoll或者select的lua_nginx_module的API,和connect配套使用?就像C那样

violoncello

unread,
Apr 20, 2016, 8:29:42 AM4/20/16
to openresty
多谢doujiang大大指点!!!
我后来确实使用了 ngx.thread.spawn来并行发送新建请求,在请求数量较少的情况下,确实收到了预期的效果,即多个请求的超时不会累加。
但是当请求数量很大时,比如500,只能发出前20个左右的请求,后面的全丢失了,从前端原始请求的响应以及抓包,都证实了。
是不是本身lua light thread数量有限?不知是否能调整数量上限?
代码如下:
local ths_url = {}
for i = 1, urls_num do  --urls_num对应请求的个数
    ths_url[i] = ngx.thread.spawn(send_data, url[i], srvs, srvs_num)  --send_data是发送请求的函数
end

for i = 1, urls_num do
    ngx.thread.wait(ths_url[i])
end

DeJiang Zhu

unread,
Apr 22, 2016, 12:00:07 PM4/22/16
to open...@googlegroups.com
Hello

在 2016年4月20日 下午8:29,violoncello <cello...@gmail.com>写道:
多谢doujiang大大指点!!!
我后来确实使用了 ngx.thread.spawn来并行发送新建请求,在请求数量较少的情况下,确实收到了预期的效果,即多个请求的超时不会累加。
但是当请求数量很大时,比如500,只能发出前20个左右的请求,后面的全丢失了,从前端原始请求的响应以及抓包,都证实了。
是不是本身lua light thread数量有限?不知是否能调整数量上限?

没有这样的限制
 
代码如下:
local ths_url = {}
for i = 1, urls_num do  --urls_num对应请求的个数
    ths_url[i] = ngx.thread.spawn(send_data, url[i], srvs, srvs_num)  --send_data是发送请求的函数
end

你的 send_data 是否有执行失败的记录呢
 

for i = 1, urls_num do
    ngx.thread.wait(ths_url[i])
end

--

Yichun Zhang (agentzh)

unread,
Apr 22, 2016, 3:12:09 PM4/22/16
to openresty
Hello!

2016-04-19 7:23 GMT-07:00 YuanSheng Wang:
> 由于 connect 操作是异步执行的,当它发生阻塞的时候,是不会影响其他请求的任何网络动作。所以从两个请求送达到全部接收到结果,总耗时是 3 秒。
>

应当特别小心“异步”这个术语。从 Lua 层面上看,connect 调用其实是*同步*的,即 connect
函数调用在操作结束后才会返回。如果是异步的话,应该不等连接建立完成就立即返回。

从性能的角度看,重要的并不是同步还是异步,而是非阻塞 IO 和 IO 多路复用。异步操作也不一定就是使用非阻塞 IO 的,比如通过 OS
线程实现的异步操作,还是可能会使用阻塞 IO,从而影响并发能力(就像 Apache 的 worker mpm 那样)。

Regards,
-agentzh

violoncello

unread,
May 4, 2016, 10:20:24 PM5/4/16
to openresty
Hello

受教了,多谢doujiang和chun哥指点!!!

确实在lua-nginx-module里对light thread数量没有限制,但过多使用也会对内存造成一定负担
确认connect是同步工作后,与ngx.thread.spawn配合使用,并设置好nginx的最大连接数,一切OK!!!
Reply all
Reply to author
Forward
0 new messages