同一 PHP 脚本上的并行请求会导致第二次长时间延迟


Parallel request on the same PHP script causes a second long delay

Background

这让我疯狂了几个星期。我使用MrClay的PHP Minify脚本来缩小和连接我的JS和CSS。它工作得很好,我的所有文件都合并为common.css和common.js,它们是虚拟文件,翻译为链接到脚本,如下所示:

RewriteRule ^common.js$ /tynamic/min/?g=js [L,QSA]
RewriteRule ^common.css$ /tynamic/min/?g=css [L,QSA]

还附加了一个查询字符串来表示这些文件的一个版本,并且它们具有长达 3 年的缓存,因此访问过我网站的人将来访问该网站时可能永远不必下载任何 CSS 或 JS(如果它们没有改变,显然)。到目前为止,一切正常。

问题所在

通常(可悲的是并非总是如此),当我的浏览器要求输入这两个文件(同时完成)时,其中一个文件需要一秒钟才能返回。它总是请求稍后到达服务器,因此它通常是HTML中较晚的请求,但它不是规则。

请参阅以下屏幕截图:

取自我的火狐

平多姆的测试报告

我可以接受服务器将另一个文件放入队列并在第一个文件之后处理它,但这并不需要整整一秒钟。还有几件事:在这种情况下,没有执行像连接或gzipping这样的操作。该脚本仅对现有的预压缩文件执行 fpassthru()。然而,它不会一直发生。那里有点奇怪,如果我进行大量连续的页面加载,例如 30 个或更多,当两个文件都在微不足道的时间内处理时,它会恢复"正常"。然后当我在一段时间后检查时,它又回到了第二个挂起。时间总是超过一秒钟

我已经尝试过的

  1. if($_GET["g"]=="js") exit;放在脚本的开头。

没错,这无济于事。文件仍然延迟,什么也没输出。只需exit;(对于两个文件)即可工作... :)

  1. 对脚本进行计时

两次运行都报告其运行的最小时间(单位或几十毫秒),因此没有函数会延迟它。

  1. 不同的服务器/托管

没有帮助,3个不同的服务器和托管服务提供商。它与托管无关。

  1. 制作脚本的完整副本

所以我复制了完整的脚本目录,以确保两次运行都是由不同的文件集进行的 - 没有帮助。

  1. 禁用文件锁定以及对脚本配置或脚本本身的其他调整。

到目前为止,我还没有想出任何:(

  1. 不同的脚本 - 做其他事情。

这很有趣,修改文件以执行其他操作,例如执行扫描并选择一个文件也无济于事。另一项分析显示,PHP脚本每秒分配给释放CPU线程。因此,如果有例如 5 个线程,并且需要一次运行 6 个脚本,那么前 5 个脚本大约在 10 毫秒内完成,但第 6 个必须等待整整一秒钟才能开始处理......为什么会这样?

提前非常感谢为帮助我所做的任何努力

> CBroe 可能是对的。如果您使用的是会话 (session_start()),PHP 一次只会向一个客户端 (session_id) 提供一个请求。当一个请求正在被处理时,另一个请求将排队,直到第一个请求写入会话。会话文件被锁定,以防止多个请求写入同一会话,这可能会导致意外结果。会话在脚本完成时或通过调用 session_write_close() 写入。这将释放您的会话以用于下一个请求。

但是,我觉得有义务告诉你,你做错了。你不应该用PHP最小化JS和CSS。原因如下:

  1. 为此使用 PHP 会导致服务器上不必要的负载
  2. 浏览器仍在请求文件以获取 304 响应 - 再次对服务器造成不必要的负载并降低用户体验(这些请求仍然需要时间)
  3. 很难
  4. 构建一个好的缩小工具,也没有必要重新发明轮子。更好的是现成的。
  5. 还有更多原因...

我建议你最好把时间花在不要写缩小脚本上,而是花在学习构建工具(Grunt 或 Gulp)上,这些工具可以为你完成这项工作,而且比你想要/能够用 PHP 编写的要多得多。

简而言之,整个过程是如何工作的

  1. 将服务器设置为发送过期标头。这将阻止客户端甚至请求更改文件。谷歌如何使用Apache完成此操作:https://www.google.com/search?q=apache+expires+htaccess&ie=utf-8&oe=utf-8&gws_rd=cr&ei=y12dVrqKG8KvsAHFiKjYDA
  2. 设置上述工具来"构建"您的缩小资源 - 连接多个文件,"编译"样式表,缩小等。因此,您将这些构建的文件放在磁盘上,并由Web服务器直接提供服务。
  3. 您只需将网站设置为在生产中使用缩减的资源。(您希望能够在开发中调试完整的源代码)。
  4. 当您对网站部署任何更改时。

设置它的技能对于任何Web开发人员来说都非常方便。此外,这将释放您构建 Web 应用程序本身的时间。

问题没有解决,但是我找到了一个托管服务提供商,这个问题根本没有出现。然后这是一个托管问题,它必须是它如何将 PHP 线程分配给请求的东西 - 似乎我的旧主机只用一秒钟的刻度来做到这一点。这就是我现在所知道的。