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

试了下,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也是不通了,有什么解决方案么
    没有ngx.yield()这样的方法。

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

    在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
    试了下,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也是不通了,有什么解决方案么
      那我想要实现切时间片,但是没有那一毫秒的延时该如何做呢,有什么好的思路么?

      在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:
      没有ngx.yield()这样的方法。

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

      在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
      试了下,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也是不通了,有什么解决方案么
        在lua和Nginx中貌似没有好的办法。
        你这种用法只适合另启进程去跑了

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

        在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:
        没有ngx.yield()这样的方法。

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

        在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
        试了下,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也是不通了,有什么解决方案么


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


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

          在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:
          没有ngx.yield()这样的方法。

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

          在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
          试了下,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也是不通了,有什么解决方案么

          --



          --

          membphis
            coroutine.yield 这个 API 不知能不能满足你的需求?
            https://github.com/openresty/lua-nginx-module#coroutineyield

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

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

            在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:
            没有ngx.yield()这样的方法。

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

            在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
            试了下,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也是不通了,有什么解决方案么
              不可以的,coroutine那个还得自己来调度,我想要的是openresty来帮我调度的那种

              在 2017年4月20日星期四 UTC+8上午10:54:18,Zexuan Luo写道:
              coroutine.yield 这个 API 不知能不能满足你的需求?
              https://github.com/openresty/lua-nginx-module#coroutineyield

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

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

              在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:
              没有ngx.yield()这样的方法。

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

              在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
              试了下,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也是不通了,有什么解决方案么
                这个是更新ngx的时间缓存,我想要类似golang中的runtime.Gosched()来手动切换cpu的时间片

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


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


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

                在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:
                没有ngx.yield()这样的方法。

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

                在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
                试了下,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也是不通了,有什么解决方案么

                --



                --

                membphis
                  重新看了下 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 应该是可行的。

                  在 2017年4月20日 上午11:52,cheng ye <iih...@gmail.com>写道:
                  不可以的,coroutine那个还得自己来调度,我想要的是openresty来帮我调度的那种

                  在 2017年4月20日星期四 UTC+8上午10:54:18,Zexuan Luo写道:
                  coroutine.yield 这个 API 不知能不能满足你的需求?
                  https://github.com/openresty/lua-nginx-module#coroutineyield

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

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

                  在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:
                  没有ngx.yield()这样的方法。

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

                  在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
                  试了下,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也是不通了,有什么解决方案么

                  --

                    您好,我刚刚试了下,发现还是不行,我把上面的ngx.sleep(0.001)换成了coroutine.yield()还是会出现阻塞的情况,不可以的接受其他请求的

                    在 2017年4月20日星期四 UTC+8下午5:10:41,Zexuan Luo写道:
                    重新看了下 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 应该是可行的。

                    在 2017年4月20日 上午11:52,cheng ye <iihe...@gmail.com>写道:
                    不可以的,coroutine那个还得自己来调度,我想要的是openresty来帮我调度的那种

                    在 2017年4月20日星期四 UTC+8上午10:54:18,Zexuan Luo写道:
                    coroutine.yield 这个 API 不知能不能满足你的需求?
                    https://github.com/openresty/lua-nginx-module#coroutineyield

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

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

                    在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:
                    没有ngx.yield()这样的方法。

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

                    在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
                    试了下,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也是不通了,有什么解决方案么

                    --



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



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

                       
                      在 2017年4月20日星期四 UTC+8下午5:10:41,Zexuan Luo写道:
                      重新看了下 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 应该是可行的。

                      在 2017年4月20日 上午11:52,cheng ye <iihe...@gmail.com>写道:
                      不可以的,coroutine那个还得自己来调度,我想要的是openresty来帮我调度的那种

                      在 2017年4月20日星期四 UTC+8上午10:54:18,Zexuan Luo写道:
                      coroutine.yield 这个 API 不知能不能满足你的需求?
                      https://github.com/openresty/lua-nginx-module#coroutineyield

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

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

                      在 2017年4月19日星期三 UTC+8上午10:00:29,FQ Liu写道:
                      没有ngx.yield()这样的方法。

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

                      在 2017年4月19日星期三 UTC+8上午9:44:46,cheng ye写道:
                      试了下,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也是不通了,有什么解决方案么

                      --

                      --



                      --

                      membphis
                        但是我把参数设置为0是不起作用的,只有设置为0.001才可以。我最开始有例子的,你可以跑下。sleep 0的时候还是阻塞的
                          没错,这个是一个已知的 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 分享出来。


                          On Friday, April 21, 2017 at 2:55:21 PM UTC-7, cheng ye wrote:
                          但是我把参数设置为0是不起作用的,只有设置为0.001才可以。我最开始有例子的,你可以跑下。sleep 0的时候还是阻塞的
                            好的,我上次想在openresty的源码中添加一个ngx.yield方法,里面用lua的c API去进行yield操作,但是还是不起作用,你代码提交后,还请给个地址,告知一下,我学习一波。谢了
                              请尝试: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 <iih...@gmail.com>:
                              好的,我上次想在openresty的源码中添加一个ngx.yield方法,里面用lua的c API去进行yield操作,但是还是不起作用,你代码提交后,还请给个地址,告知一下,我学习一波。谢了

                              --

                                您好,我刚刚安装这个重新编译了下,发现上面那个问题依旧还是存在的,好像还是不行呢

                                在 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操作,但是还是不起作用,你代码提交后,还请给个地址,告知一下,我学习一波。谢了

                                --

                                  21 days later
                                  试一下:https://openresty.org/download/openresty-1.11.2.4rc0.4.tar.gz

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

                                  On Monday, April 24, 2017 at 9:08:47 PM UTC-7, cheng ye wrote:
                                  您好,我刚刚安装这个重新编译了下,发现上面那个问题依旧还是存在的,好像还是不行呢

                                  在 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操作,但是还是不起作用,你代码提交后,还请给个地址,告知一下,我学习一波。谢了

                                  --

                                    6 days later
                                    谢谢你了哈,我用一下

                                    在 2017年5月16日星期二 UTC+8上午9:49:34,dat...@openresty.com写道:
                                    试一下:https://openresty.org/download/openresty-1.11.2.4rc0.4.tar.gz

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

                                    On Monday, April 24, 2017 at 9:08:47 PM UTC-7, cheng ye wrote:
                                    您好,我刚刚安装这个重新编译了下,发现上面那个问题依旧还是存在的,好像还是不行呢

                                    在 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操作,但是还是不起作用,你代码提交后,还请给个地址,告知一下,我学习一波。谢了

                                    --

                                      Write a Reply...