只要有一个长时间运行的 PHP 脚本在服务器上运行,就无法运行其他 PHP 脚本。

4
我有一个在服务器上运行的长期PHP脚本。它通过服务器向video标签流视频(不要问我为什么这样做 :-))。它可以运行数十分钟。
问题是,在同一时间,我想使用AJAX向服务器发送请求,但在长脚本停止之前,它并不会发生。
我进一步调查了这个问题,发现了奇怪的事情。
  • 当长时间运行的PHP脚本正在运行时,我无法从同一浏览器调用任何PHP脚本(无论是AJAX还是其他)。
  • 同时,从其他浏览器可以轻松访问服务器。
  • 非PHP资产(图像、视频)可以正常访问。
  • 如果直接从.mp4文件播放视频,则不存在此问题。可以在播放视频时处理对php的AJAX请求。
我很好奇这可能是什么原因。从我所看到的,它可能是服务器和浏览器配置的组合。
我的问题是为什么会发生这种情况,以及如何解决?我希望能够在同一浏览器中运行其他PHP脚本的同时向服务器发送AJAX请求。
以下是“卡住”的请求示例。第一个请求是视频,第二个请求是我想发送的AJAX请求,在第一个请求完成之前不会有任何响应。 enter image description here 一旦第一个请求完成,第二个请求立即完成。 enter image description here Web服务器是Apache 2。在IE和Chrome中都可以重现此问题。
使用普通的jQuery $.ajax()调用发送Ajax请求。
以下是阻止AJAX请求的视频请求和响应信息。
Request GET /portal/portlet/index/id/671/call/proxyVideo?entityId=1 HTTP/1.1
Accept  */*
If-Unmodified-Since Fri, 24 Apr 2015 08:18:29 GMT
If-Match    "f91b54d-514740a87ff40"
Range   bytes=360448-261207372
User-Agent  Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Referer http://mm.mac/content
GetContentFeatures.DLNA.ORG 1
Pragma  getIfoFileURI.dlna.org
Accept-Language en-US
Accept-Encoding gzip, deflate
Host    mm.mac
Connection  Keep-Alive
Cache-Control   no-cache
Cookie  PHPSESSID=41821op72k2s24mfrsbn5gad64


Response    HTTP/1.1 206 Partial Content
Date    Tue, 01 Dec 2015 13:39:31 GMT
Server  Apache/2.4.16 (Unix) PHP/5.6.13
X-Powered-By    PHP/5.6.13
Expires Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control   no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma  no-cache
Last-Modified   Fri, 24 Apr 2015 08:18:29 GMT
ETag    "f91b54d-514740a87ff40"
Accept-Ranges   bytes
Content-Length  260846925
Access-Control-Allow-Methods    GET
Content-Range   bytes 360448-261207372/261207373
Keep-Alive  timeout=5, max=100
Connection  Keep-Alive
Content-Type    video/mp4

不要问我为什么这样做 :-) - 自动盗版? - Realitätsverlust
2
如果您正在使用默认的会话存储,则会话将被写入文件。长时间运行的请求将在会话文件上创建锁,从而阻止其他请求。您可以将会话移动到数据库中,或者在不再需要会话信息时,在长时间运行的脚本中使用 session_write_lock(),从而释放锁。 - DarkBee
2
它被称为 session_write_close() 吗? - van Stein en Groentjes
http://www.genericarticles.com/mediawiki/index.php?title=How_to_optimize_apache_web_server_for_maximum_concurrent_connections_or_increase_max_clients_in_apache - online Thomas
@vanSteinenGroentjes,没错。是我打错了:) - DarkBee
自动化盗版?并不是真的。必须通过这种丑陋的方式解决这个问题http://stackoverflow.com/questions/30101143/canvas-todataurl-gives-security-error-in-ie-11。 - Stepashka
2个回答

5

会话锁定

这个问题可能是由于会话锁定引起的。当长时间运行的PHP脚本使用session_start()时,该进程会锁定服务器上的会话文件直到完成。阻止所有尝试打开同一会话文件的其他PHP进程。

这就是为什么在同一个浏览器中会看到这种行为,但在另一台机器或不同的浏览器中却不会看到(因为会话不同)。

解决您的问题的方法是使用:

session_write_close();

每当您不需要向会话中写入内容时,仍然可以在调用此函数时从会话变量中读取,但是如果要再次写入会话变量,则需要使用 session_start() 再次打开会话。
您可以在这里了解更多关于这个问题的信息。
下面是一个例子(来自链接页面):
// start the session
session_start();

// I can read/write to session
$_SESSION['latestRequestTime'] = time();

// close the session for writing
session_write_close();

// now do my long-running code.
// still able to read from session, but not write
$twitterId = $_SESSION['twitterId'];

//when you want to write again do session_start() before and close after.

感谢您提供详细的答案。 - Stepashka

0

同一时间只有1个PHP脚本可以访问相同的用户会话,所有其他脚本都必须等待第一个脚本完成。

这是因为会话文件写锁定。

解决方案:

  1. 如果您在长脚本中不需要会话,请勿使用会话
  2. 尽快调用session_write_close()以解锁会话文件http://php.net/manual/en/function.session-write-close.php

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接