PHP + Apache 等待时间过长

PHP + Apache 等待时间过长

我在排除专用网络服务器故障时遇到了一些麻烦。最近,我的网站每秒的请求量激增,然后崩溃了。

该盒子原来有 8GB RAM、8 核 Xeon E3-1230、1TB 7,200 RPM 磁盘(无 Raid)、100Mbit 专用网络。

峰值之后,我将 RAM 增加到 24GB,以支持更多并发用户。

Apache 似乎处理得很好,即使有 3000 个并发用户,它也会非常快速地返回 HTML 和静态内容(未缓存)。

为了进一步测试 Apache/HTML 和 Apache/PHP 之间的差异,我运行了ab

test.html和都test.php具有完全相同的静态内容,PHP 不调用任何includes 并且不与 MySQL 连接。

HTML 测试

ab -n 500 -c 50 http://www.~~.com/test.html

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      252  375 190.3    276    1399
Processing:   254  354 121.5    282     657
Waiting:      253  353 121.4    280     653
Total:        510  730 231.7    573    1675

PHP 测试

ab -n 500 -c 50 http://www.~~~.com/test.php

Connect:      248  275  51.1    267    1316
Processing:   256 4167 6210.2   2262   41489
Waiting:      253 4166 6210.2   2262   41489
Total:        509 4442 6212.4   2523   41754

Pingdom 还报告访问 PHP 脚本时需要等待很长时间。 在此处输入图片描述

我在 WebPageTest.org 上得到了类似的结果,尽管更好,但第一次字节是F

           Load Time   **First Byte**   Start Render    DOM Elements    Time    Requests    Bytes In    Time    Requests    Bytes In
First View  2.061s  **0.839s**  0.000s  55  2.061s  20  428 KB  2.061s  20  430 KB

以下是我的top结果: 在此处输入图片描述

输入/输出测试

在重负载下,wa% 可以在几毫秒内增加到 95%。

我在加载期间运行了 iostat:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           8.37    0.00    5.18    0.56    0.00   85.88

Device:         rrqm/s   wrqm/s   r/s   w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda1              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb               0.00    45.50  3.00 48.00   136.00   748.00    17.33     3.05   59.76   2.53  12.90
sdb1              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb2              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb3              0.00    45.50  3.00 48.00   136.00   748.00    17.33     3.05   59.76   2.53  12.90

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           4.00    0.00    3.56    0.69    0.00   91.75

Device:         rrqm/s   wrqm/s   r/s   w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda1              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb               6.00   118.50  9.50 21.00   996.00  1116.00    69.25     0.29    9.44   1.66   5.05
sdb1              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb2              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb3              6.00   118.50  9.50 21.00   996.00  1116.00    69.25     0.29    9.44   1.66   5.05

对我来说,这看起来并不坏,但我可能忽略了一些东西。

我在用着FCGI

<IfModule mod_fcgid.c>
FcgidMaxRequestLen 1547483648
FcgidMaxRequestInMem 52485760
FcgidIdleScanInterval 15000
FcgidBusyTimeout 15000
FcgidProcessLifeTime 7200
FcgidConnectTimeout 1800
FcgidIOTimeout 1800
PHP_Fix_Pathinfo_Enable 1
FcgidMaxRequestsPerProcess 1000
</IfModule>

这是我的 Apache Conf(我使用的是 2.4.x)

Timeout 60
TraceEnable Off
ServerSignature Off
ServerTokens ProductOnly
FileETag None
StartServers 10
<IfModule prefork.c>
MinSpareServers 5
MaxSpareServers 15
</IfModule>
<IfModule itk.c>
MinSpareServers 5
MaxSpareServers 15
</IfModule>
ServerLimit 2200
MaxRequestWorkers 2000
MaxConnectionsPerChild 15000
KeepAlive On
KeepAliveTimeout 1
MaxKeepAliveRequests 2000

我查看了我的 Apache 错误日志和访问日志。没有发现任何异常。

我实在很困惑。

我已尝试关闭防火墙。

我已尝试增加最大连接数。

我已经优化了 mySQL 并删除了许多慢查询(>0.5 秒)。

我还能做什么?有什么可以帮助我识别问题吗?任何帮助都将不胜感激。

附言:

值得注意的是,即使服务器访问量很大,PHPMyAdmin 和 cPanel 仍然反应灵敏。除了网站上的 PHP,其他一切都没有延迟。

答案1

我认为您的问题只是硬盘及其访问时间。Apache 可以在内存中缓存 html 页面,但 php 脚本不会被缓存;每次都需要重新执行。因此,php 解释器被调用并从硬盘读取脚本。这需要花费大量时间。服务器上最慢的东西是您的硬盘。在我的 PC 上,从我的 SSD 和我的 HDD 启动的应用程序之间存在极大差异(SSD 快 10 倍!)。如果您的 HDD 可以正常工作,那么执行 php 脚本的延迟可能会大幅增加。

可能的解决方案:获取 SSD(可能是一个小型 SSD,仅用于存储经常访问的数据,例如脚本),并尽量减少服务器上的脚本调用(和 HDD 访问)。确保文件系统已进行碎片整理(通常自动完成)。如果您的 php 脚本经常创建相同的内容,请尝试将它们缓存到 html 文件中。

这个答案也可以帮助您:https://stackoverflow.com/questions/4181865/apache-php-caching

答案2

您正在测试的 HTML 文件只是一个普通文件,Apache 所要做的就是执行一些系统调用(打开、读取),然后提供其内容。

另一方面,PHP 实际上是一个相当“繁重”的选项:它是一个完整的解释器(字节码编译器?)。而且由于您使用的是并发测试(-c),谁知道请求对它的多路复用程度如何?这根本就不是 Apache 的问题,而是 PHP 的问题。

我会做什么:

  1. 切换到 Apache MPM(多进程中的多线程)。

  2. 进行顺序测试(没有多个并发请求),进行比较。

  3. 在 apache 进程上运行valgrind或类似操作,查看大部分 CPU 时间都花在哪里(apache 还是 PHP)。

  4. 运行相同的测试,但通过 nginx 提供此页面。由于 nginx 基于异步模型并且速度非常快,因此如果您得到类似的结果,则 PHP 是罪魁祸首。

  5. 最后,您可以安装 Zend Optimizer(30 天试用版免费)或类似这样的软件:https://github.com/zendtech/ZendOptimizerPlus

实际上,将静态文件与动态生成的网页进行比较就像苹果与橘子之间的比较。在这方面,没有一种典型的解决方案(Python mod-apache、Django、PHP 等)会非常快,至少与静态文件相比是如此。Node.js 可能是一个例外,因为它直接在异步模型中对网页进行某种“低级”编程。

PS 您尚未引用php.ini内容。请发布并/或对其进行修改。

相关内容