1. 首先我解释下业务场景:
主线程: 通过tcpsock:receive()每次接收1M数据
另发送线程:通过tcpsock:send()分别发送接收到的1M数据
当发送线程由于send()的返回11(EAGAIN),而由ngx_lua线程调度器调度主线程执行时,则主线程调用coroutine.yield()切换到发送线程继续执行,直到所有的数据发送完成
2. 现象及问题:
当发送线程由于send()的返回11(EAGAIN), 在主线程中调用coroutine.yield()时, ngx_lua线程调度器并没有resume发送线程, 而是继续在主线程中执行.
3 个人分析:
是不是由于ngx_http_lua_util.c中的f (ctx->posted_threads) 为false?
1095 if (ctx->posted_threads) {$
1096 ngx_http_lua_post_thread(r, ctx, ctx->cur_co_ctx);$
1097 ctx->cur_co_ctx = NULL;$
1098 return NGX_AGAIN;$
1099 }$
4. 部分日志:
2014/10/17 18:29:01 [debug] 18726#0: *1 send: fd:12 -1 of 104519680
2014/10/17 18:29:01 [debug] 18726#0: *1 send() not ready (11: Resource temporarily unavailable)
2014/10/17 18:29:01 [debug] 18726#0: *1 event timer add: 12: 3000:1413541744851
2014/10/17 18:29:01 [debug] 18726#0: *1 lua resume returned 1
2014/10/17 18:29:01 [debug] 18726#0: *1 lua thread yielded
2014/10/17 18:29:01 [debug] 18726#0: *1 lua run thread returned -2
2014/10/17 18:29:01 [debug] 18726#0: *1 lua run thread, top:0 c:1
2014/10/17 18:29:01 [debug] 18726#0: *1 lua resume returned 1
2014/10/17 18:29:01 [debug] 18726#0: *1 lua thread yielded
2014/10/17 18:29:01 [debug] 18726#0: *1 lua coroutine: yield
2014/10/17 18:29:01 [debug] 18726#0: *1 lua resume returned 1
2014/10/17 18:29:01 [debug] 18726#0: *1 lua thread yielded
我是在nginx debug模式下在日志文件中看到send()返回错误码是11(EAGAIN),
在 2014年10月19日星期日UTC+8上午1时07分09秒,agentzh写道:
Hello!
2014-10-18 4:57 GMT-07:00 sven peng:
> 在使用lua-nginx-module的coroutine时遇到一个奇怪的事情,
> 我用ngx.thread.spawn新建一个coroutine调用ngx.socket.tcp:send()函数发送数据时,send()函数在返回EAGAIN后,
TCP cosocket 对象的 send() 函数并不会返回 EAGAIN,见其官方文档:
https://github.com/openresty/lua-nginx-module#tcpsocksend
你究竟看到的是什么返回值?
> 我就在主coroutine中调用coroutine.yield()试图重新调回那个coroutine执行,可是结果并没有切换那个coroutine执行而是一直在主coroutine中.
在 ngx_lua 中,通过 ngx.thread.spawn() 创建的对象是“轻量级线程”,其语义并不同于由
coroutine.create() 创建的 Lua 协程的标准语义,虽然“轻量级线程”也是基于 Lua
协程来实现的。因此,对“轻量级线程”调用 coroutine.yield() 的效果也不同于标准 Lua 协程。引用一下相关文档:
https://github.com/openresty/lua-nginx-module#ngxthreadspawn
"A 'light thread' will keep running exclusively on the CPU until
1. a (nonblocking) I/O operation cannot be completed in a single run,
2. it calls coroutine.yield to actively give up execution, or
...
For the first two cases, the "light thread" will usually be resumed
later by the ngx_lua scheduler unless a ‘stop-the-world’ event
happens."
换言之,被用户 Lua 代码主动 yield 的轻量级线程会由 ngx_lua 的协程调度器自动 resume.
另外,请加入 openresty 中文邮件列表讨论这样的问题,而不要直接发邮件给我。谢谢合作!细节请见
http://openresty.org/#Community
Regards,
-agentzh
P.S. 同时抄送给 openresty 中文邮件列表。