3

如果我有一个 PHP 页面正在执行一项需要很长时间的任务,并且我尝试同时从同一个站点加载另一个页面,则该页面将在第一页超时之前不会加载。例如,如果我的超时设置为 60 秒,那么直到需要很长时间才能加载/超时的页面后 60 秒,我才能加载任何其他页面。据我所知,这是预期的行为。

我想弄清楚的是,造成上述情况的错误/长时间加载 PHP 脚本是否也会影响同一网络上的其他人。我个人认为这是一个浏览器问题(即,如果我在 chrome 中加载http://somesite.com/myscript.php并且它开始在后台运行它很神奇,我就无法加载http://somesite.com/ myscript2.php直到超时,但我可以在 Firefox 中加载该页面)。但是,我听到了相互矛盾的说法,说超时会发生在同一网络上的每个人身上(IP 地址?)。

我的脚本适用于从 sage 导入的一些数据,并且需要很长时间才能运行 - 有时它可能会在完成之前超时(即,如果 sage 导入在一周内崩溃),所以我再次运行它,它会从中断的地方继续. 我担心办公室的其他工作人员在运行时将无法访问该站点。

4

2 回答 2

3

您在这里遇到的问题实际上与(我猜)您正在使用session的事实有关。这可能有点牵强,但它会完全解释你所描述的。

这实际上不是“预期行为”,除非您的 Web 服务器设置为使用单个线程运行单个进程,我对此表示高度怀疑。这会造成网络服务器在任何时候只能处理一个请求的情况,这会影响网络上的每个人。这正是为什么您的 Web 服务器可能不会这样设置的原因——事实上,我怀疑您会发现这样配置您的服务器是不可能的,因为它会使服务器有些无用。在一些聪明的 alec 插话“Node.js 怎么样?”之前 - 这是一个特例,我相信你已经很清楚了。

当 PHP 脚本打开会话时,它会对存储会话数据的文件具有排他锁。这意味着任何后续请求都将在调用时阻塞,session_start()而 PHP 尝试获取会话数据文件上的排他锁 - 它不能,因为您之前的请求仍然有一个。一旦您的上一个请求完成,它就会释放对文件的锁定,并且下一个请求能够完成。由于会话是每台机器的(实际上是每浏览会话,顾名思义,这就是它在不同浏览器中工作的原因),这不会影响您网络的其他用户,但会保留您的站点设置,以便这是一个即使对您而言,问题也是不好的做法,很容易避免。

解决方案是在session_write_close()您完成给定脚本中的会话数据后立即调用。这会导致脚本关闭会话文件并释放它的锁定。您应该尝试在开始长时间运行的过程之前完成会话数据,或者在完成之前不要调用session_start()

从理论上讲,您可以稍后在脚本中调用session_write_close()然后session_start()再次调用,但我发现 PHP 有时在这方面表现出错误行为(我认为这与 cookie 有关,但不要引用我的话)。显然,请注意设置 cookie 会修改标头,因此您必须session_start()在输出任何数据或启用输出缓冲之前调用。

例如,考虑这个脚本:

<?php

  session_start();

  if (!isset($_SESSION['someval'])) {
    $_SESSION['someval'] = 1;
  } else {
    $_SESSION['someval']++;
  }

  echo "someval is {$_SESSION['someval']}";

  sleep(10);

使用上述脚本,您必须等待 10 秒才能发出第二个请求。session_write_close()但是,如果您在该行之后添加一个调用echo,您将能够在前一个请求完成之前发出另一个请求。

于 2012-06-06T09:38:00.520 回答
0

嗯...我没有检查,但我认为对网络服务器的每个请求都是在它自己的线程中处理的。因此,不应阻止不同的请求。试试看 :-) 使用不同的浏览器并在运行大脚本时访问您的页面!

Err.. 我只是看到这对你有用:-) 它也应该适用于其他人。

于 2012-06-06T09:28:11.717 回答