2

对这个问题感兴趣 - 如何正确停止带有 sleep 的 while 循环。我实施“长轮询”以快速更新网站上的信息(警告,其他信息)的事实。

剧本的本质

1.我们将GET-request发送到脚本所在的PHP-page。

2.脚本运行循环while

3.在这个系列中,有2 个条件和最后的 sleep(1),它暂停了循环的执行。

   -如果循环运行更多秒30 - 分别停止循环和脚本的执行。

   -如果您的站点有新信息,请说“警告” - 将结果提供给用户并停止循环。

问题 如果用户关闭浏览器窗口或重新加载页面 - 将在脚本上执行新查询,这将再次开始循环。但是在这种情况下,循环while的先前执行将不会停止,直到它们在其中至少工作了一个条件。如果用户向页面发送大量请求 - 服务器的内存开始启动,结果全部挂起,直到 all while不会停止执行。

QUESTION 如何停止循环和脚本作为一个整体,当您运行页面时重新加载或客户端?此刻我做了以下事情。当您运行我们生成的脚本时,我们会收到一个分配给变量的随机数,并且与会话相同。进一步内陆同时做一个条件,其中变量必须是会话的值。如果为假 - 停止循环。如果我们在 new 上运行脚本 - 会话的值会发生变化,因此所有先前的性能都会在停止时发生变化。我可以使用那个选项吗?多少是安全的?

更新.PHP

 // Initialize the user's session
 $session = Session::instance();

        $rand = rand();
        $session->set('user_update_key', $rand);
        $key = $rand;

        $limit = 20;
        $seconds = 0;

        set_time_limit($limit + 1);

        while (TRUE) {
            if (Session::instance()->get('user_update_key') == $key) {

                if (there are updates. if there is - output) {
                    echo 'update information';
                    flush();
                    exit;
                }
                if ($seconds == $limit) { // complete the loop at the expiration of the time.
                    echo 'Close';
                    flush();
                    exit;
                }
                $seconds++;
            } else {
                unset($session, $rand, $key, $notice, $mysession, $last_notice, $limit, $notise_return, $seconds);
                flush();
                exit;
            }
            session_write_close();
            sleep(1);
            session_start();

}

4

3 回答 3

2

请注意,通常 PHP 和 Apache 不适合长轮询。我不知道当你使用 nginx 时情况如何,但几个月前我不得不在 Apache 上做一些长时间的轮询工作。在我们开始生产之前,一切看起来都很好。事实证明,Apache 的限制使您无法维持长期的连接。

在允许大约20个用户登录并打开3-4张网页卡后,服务器挂起并拒绝接受任何新请求。还有一些浏览器限制会阻止您维护与一台主机的过多 http 连接。虽然有解决方法 - 使用子域。

我试图弄清楚如何解决 id,在 StackOverflow 上问了十几个问题,一切都以使用轻量级的 node.js + socket.io 结束,它可以轻松处理数千个同时连接。

我知道这篇文章不能回答您最初的问题,但是在我花了几周时间开发一些不起作用的东西之后,我希望这些信息对您有所帮助。

于 2013-05-22T11:54:59.600 回答
0

为什么不使用 cronjob 定期在后台运行进程,然后将 AJAX 放置在拉数据库检查警报的网页上。否则你会遇到性能问题。

于 2013-05-22T12:01:04.373 回答
0

您的 while 条件是不变的,而在实践中却不是。如果成功,函数 sleep() 将返回 0,因此,如果您根据 sleep() 的返回值的变化重写您的 while 条件反应,那么它是否可以按设计工作,请参阅: http: //php.net/manual/ zh/function.sleep.php

对于线程和其他功能,了解您在哪个操作系统上工作始终很重要。我有 Ubuntu,它的反应与文档所述不同。

function interruptedSleep(){
  $cond = true;
  while($cond){
   $i = sleep(10);
   if($i == 0){
     $cond = false;
   }
  }
 }

当您通过关闭浏览器来中断睡眠时,sleep 函数将返回 0 并且 while 循环被中止,并且程序将在 while 之后直接继续。它不会抛出异常。

于 2013-05-22T11:50:39.597 回答