openresty中有什么方法能手动切换时间片么?例如像ngx.yield()这种方法有么

399 views
Skip to first unread message

cheng ye

unread,
Apr 18, 2017, 9:44:46 PM4/18/17
to openresty
试了下,ngx.sleep(0.001)可以切换出时间片,但是ngx.sleep(0)是不可以的
location /lua {
default_type text/html;
content_by_lua_block {
while true do
ngx.sleep(0.001);
end

ngx.say("hhh")
}
}
location /test {
default_type text/html;
content_by_lua_block {
ngx.say("hhh")
}
}

这个在请求/lua时再次请求/test时有响应的,当时这样会sleep 0.001秒,改成ngx.sleep(0) 却是切换不了时间片的,连请求/test也是不通了,有什么解决方案么

FQ Liu

unread,
Apr 18, 2017, 10:00:29 PM4/18/17
to openresty
没有ngx.yield()这样的方法。

Nginx是事件驱动的,
ngx.sleep导致yield时,定时器超时后执行resume.
ngx.socket导致yield时,epoll收集到事件后执行resume.
协程如果可以自己yield的话,谁去调用resume继续执行呢?没有的话协程挂在那没人管,成僵尸协程了。

在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
Message has been deleted

cheng ye

unread,
Apr 18, 2017, 10:08:21 PM4/18/17
to openresty
那我想要实现切时间片,但是没有那一毫秒的延时该如何做呢,有什么好的思路么?

在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:

FQ Liu

unread,
Apr 18, 2017, 11:58:50 PM4/18/17
to openresty
在lua和Nginx中貌似没有好的办法。
你这种用法只适合另启进程去跑了

在 2017年4月19日星期三 UTC+8上午10:08:21,cheng ye写道:

Yuansheng Wang

unread,
Apr 19, 2017, 6:19:51 AM4/19/17
to open...@googlegroups.com


2017-04-19 10:08 GMT+08:00 cheng ye <iihe...@gmail.com>:
那我想要实现切时间片,但是没有那一毫秒的延时该如何做呢,有什么好的思路么?


这个是你需要的么?不太明白 切时间片 是什么意思。 :)
 

--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+unsubscribe@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



--

membphis

Zexuan Luo

unread,
Apr 19, 2017, 10:54:18 PM4/19/17
to openresty
coroutine.yield 这个 API 不知能不能满足你的需求?
https://github.com/openresty/lua-nginx-module#coroutineyield

需要把逻辑包装在 coroutine.create 里面。


在 2017年4月19日星期三 UTC+8上午10:08:21,cheng ye写道:
那我想要实现切时间片,但是没有那一毫秒的延时该如何做呢,有什么好的思路么?

cheng ye

unread,
Apr 19, 2017, 11:52:10 PM4/19/17
to openresty
不可以的,coroutine那个还得自己来调度,我想要的是openresty来帮我调度的那种

在 2017年4月20日星期四 UTC+8上午10:54:18,Zexuan Luo写道:

cheng ye

unread,
Apr 19, 2017, 11:56:56 PM4/19/17
to openresty
这个是更新ngx的时间缓存,我想要类似golang中的runtime.Gosched()来手动切换cpu的时间片

在 2017年4月19日星期三 UTC+8下午6:19:51,Yuansheng写道:


订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com



--

membphis

Zexuan Luo

unread,
Apr 20, 2017, 5:10:41 AM4/20/17
to open...@googlegroups.com
重新看了下 coroutine.yield 这个 API,发现这个方法不需要依靠 coroutine.create。
因为 OpenResty 跑 content_by_lua 是在一个独立的 coroutine 里面跑,所以 coroutine.yield 也可以 yield 出当前的请求。

把日志级别调整到 debug 级别,然后压测下 openresty 程序,加了 coroutine.yield 的代码会产生如下日志:
2017/04/20 16:58:21 [debug] 51551#1025332: *190 lua resume returned 1
2017/04/20 16:58:21 [debug] 51551#1025332: *190 lua thread yielded
2017/04/20 16:58:21 [debug] 51551#1025332: *190 lua coroutine: yield

说明直接在 content_by_lua 里面 yield 应该是可行的。

--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+unsubscribe@googlegroups.com

cheng ye

unread,
Apr 20, 2017, 5:25:53 AM4/20/17
to openresty
您好,我刚刚试了下,发现还是不行,我把上面的ngx.sleep(0.001)换成了coroutine.yield()还是会出现阻塞的情况,不可以的接受其他请求的

在 2017年4月20日星期四 UTC+8下午5:10:41,Zexuan Luo写道:
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com

Yuansheng Wang

unread,
Apr 21, 2017, 1:03:42 PM4/21/17
to open...@googlegroups.com
2017-04-20 17:25 GMT+08:00 cheng ye <iihe...@gmail.com>:
您好,我刚刚试了下,发现还是不行,我把上面的ngx.sleep(0.001)换成了coroutine.yield()还是会出现阻塞的情况,不可以的接受其他请求的



是给 nginx timer 添加了 delay 为 0 的 timer。

 
订阅: 请发空白邮件到 openresty+subscribe@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+unsubscribe@googlegroups.com



--

membphis

cheng ye

unread,
Apr 21, 2017, 5:55:21 PM4/21/17
to openresty
但是我把参数设置为0是不起作用的,只有设置为0.001才可以。我最开始有例子的,你可以跑下。sleep 0的时候还是阻塞的

dat...@openresty.com

unread,
Apr 21, 2017, 7:31:55 PM4/21/17
to openresty
没错,这个是一个已知的 OpenResty 局限,虽然 ngx.sleep(0) 可以执行,但是因为 NGINX 会在跑完 epoll 的事件后再跑 timer,而 ngx.sleep(0) 直接在 timer 的红黑树里插了一个 delay = 0 的节点,在 epoll 的事件跑完后 coroutine 会立刻被重新 schedule,无法达到时间片的效果。

coroutine.yield() 在这里也是不可以的。即使你 call 了 coroutine.yield() OpenResty 也不会在线程结束(或者调用了阻塞操作)之前触发事件循环,这样新的连接还是无法接受。

我有一个小的 patch 可以确保 ngx.sleep(0) 时候等到下一个事件循环再运行,近期会发 PR 分享出来。

cheng ye

unread,
Apr 23, 2017, 11:29:08 PM4/23/17
to openresty
好的,我上次想在openresty的源码中添加一个ngx.yield方法,里面用lua的c API去进行yield操作,但是还是不起作用,你代码提交后,还请给个地址,告知一下,我学习一波。谢了

Datong Sun

unread,
Apr 24, 2017, 6:37:20 PM4/24/17
to open...@googlegroups.com
请尝试:https://github.com/openresty/lua-nginx-module/pull/1052

这个 patch 打过以后 ngx.sleep(0) 会保证事件循环不会被 block。

注意这个 patch 需要跟 https://github.com/openresty/openresty/pull/252 一起使用,否则会有编译错误。

2017-04-23 20:29 GMT-07:00 cheng ye <iihe...@gmail.com>:
好的,我上次想在openresty的源码中添加一个ngx.yield方法,里面用lua的c API去进行yield操作,但是还是不起作用,你代码提交后,还请给个地址,告知一下,我学习一波。谢了

cheng ye

unread,
Apr 25, 2017, 12:08:47 AM4/25/17
to openresty
您好,我刚刚安装这个重新编译了下,发现上面那个问题依旧还是存在的,好像还是不行呢

在 2017年4月25日星期二 UTC+8上午6:37:20,Datong Sun写道:
请尝试:https://github.com/openresty/lua-nginx-module/pull/1052

这个 patch 打过以后 ngx.sleep(0) 会保证事件循环不会被 block。

注意这个 patch 需要跟 https://github.com/openresty/openresty/pull/252 一起使用,否则会有编译错误。
2017-04-23 20:29 GMT-07:00 cheng ye <iihe...@gmail.com>:
好的,我上次想在openresty的源码中添加一个ngx.yield方法,里面用lua的c API去进行yield操作,但是还是不起作用,你代码提交后,还请给个地址,告知一下,我学习一波。谢了

--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com

dat...@openresty.com

unread,
May 15, 2017, 9:49:34 PM5/15/17
to openresty
试一下:https://openresty.org/download/openresty-1.11.2.4rc0.4.tar.gz

这个测试版本已经包含了我说的 patch。

cheng ye

unread,
May 22, 2017, 12:13:36 AM5/22/17
to openresty
谢谢你了哈,我用一下

在 2017年5月16日星期二 UTC+8上午9:49:34,dat...@openresty.com写道:
Reply all
Reply to author
Forward
0 new messages