PHP生成页面,但不会立即将它们返回给用户

时间:2011-05-27 18:24:44

标签: php apache

我目前正在测试我正在整理的服务器设置的负载能力。 apache2服务器上安装了PHP 5.X,它连接到单独机器上的主数据库,然后连接到2个从服务器中的1个来进行读取。

如果我自己调用它,我的测试页面需要0.2秒生成。我在另一台服务器上创建了一个php脚本,它可以同时调用65个测试页面。测试页面在整个页面中使用微量基准测试,让我知道每个部分需要多长时间。正如预期的那样 - 至少对我来说,如果有人对此有任何意见或建议,请随意评论 - 页面的SQL部分需要很短的时间来收到它接收的第一对请求然后降级,因为其余的查询堆积起来,必须等待。我认为它可能是磁盘IO问题,但在固态驱动器上进行测试时会发生相同的行为。

我的问题是创建了大约30个左右的65页,并按照我的预期由我的测试脚本加载。我的基准测试表示该页面是在3秒内创建的,我的测试脚本表示它在3.1秒内完全收到了该页面。差别并不大。问题是,对于其他请求,我的基准测试表示页面在3秒内加载,但测试脚本在6秒内没有完全收到页面。这是由apache服务器生成的页面之间的完整3秒,并发送回我的测试脚本请求它。为了确保它不是测试脚本的问题,我尝试在运行时在本地浏览器中加载页面,并通过Chrome中的时间线窗口确认相同的延迟。

我已经为Apache尝试了各种配置,但似乎无法找到导致此延迟的原因。我最近的尝试如下。该机器是四核AMD 2.8Ghz,配备2Ghz Ram。任何有关配置的帮助,或其他建议,将不胜感激。 - 很抱歉这个问题很长。

我应该提一下,我在脚本运行时监视资源,并且CPU达到最大9%的负载,并且总是至少有1 GB的ram。

我还要提到,当我查询的所有内容都是静态HTML页面时,会发生同样类型的事情。第一对夫妇需要.X秒,然后慢慢升至3秒。

LockFile ${APACHE_LOCK_DIR}/accept.lock
PidFile ${APACHE_PID_FILE}
Timeout 120
MaxClients            150
KeepAlive On
KeepAliveTimeout 4
MaxKeepAliveRequests 150

Header always append x-frame-options sameorigin

    StartServers         50
    MinSpareServers      25
    MaxSpareServers      50
    MaxClients          150
    MaxRequestsPerChild   0


User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}
AccessFileName .httpdoverride

    Order allow,deny
DefaultType text/plain
HostnameLookups Off
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
Include mods-enabled/*.load
Include mods-enabled/*.conf
Include httpd.conf
Include ports.conf

LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
Include conf.d/
Include sites-enabled/
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps



    SecRuleEngine On
    SecRequestBodyAccess On
    SecResponseBodyAccess Off
    SecUploadKeepFiles Off
    SecDebugLog /var/log/apache2/modsec_debug.log
    SecDebugLogLevel 0
    SecAuditEngine RelevantOnly
    SecAuditLogRelevantStatus ^5
    SecAuditLogParts ABIFHZ
    SecAuditLogType Serial
    SecAuditLog /var/log/apache2/modsec_audit.log
    SecRequestBodyLimit 131072000
    SecRequestBodyInMemoryLimit 131072
    SecResponseBodyLimit 524288000
        ServerTokens Full
        SecServerSignature "Microsoft-IIS/5.0"

更新: 似乎很多回应都集中在SQL是罪魁祸首的事实上。所以我在这里说明在静态HTML页面上发生相同的行为。基准测试的结果如下所示。

Concurrency Level:      10
Time taken for tests:   5.453 seconds
Complete requests:      1000
Failed requests:        899
   (Connect: 0, Receive: 0, Length: 899, Exceptions: 0)
Write errors:           0
Total transferred:      290877 bytes
HTML transferred:       55877 bytes
Requests per second:    183.38 [#/sec] (mean)
Time per request:       54.531 [ms] (mean)
Time per request:       5.453 [ms] (mean, across all concurrent requests)
Transfer rate:          52.09 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   21 250.7      0    3005
Processing:    16   33  17.8     27     138
Waiting:       16   33  17.8     27     138
Total:         16   54 253.0     27    3078

Percentage of the requests served within a certain time (ms)
  50%     27
  66%     36
  75%     42
  80%     46
  90%     58
  95%     71
  98%     90
  99%    130
 100%   3078 (longest request)

我还要说明我通过使用PHP和microtime()确定在生成页面之前发生滞后。我通过生成页面和接收它的测试脚本之间的时间差来确定这一点。区别在于,无论整个请求花了多长时间,从生成页面到我的测试页面收到它的时间点都是相同的。

感谢所有回复的人。一切都很好,我只是不能说他们中的任何一个都解决了这个问题。

2 个答案:

答案 0 :(得分:2)

还有很多其他因素,但我真的猜测你使用30M左右的时间快速产生30-40个进程并杀死你的机器有限的内存,然后继续产生新的并且崩溃交换,减慢一切都失败了。

使用2G ram,MaxClients为150,MaxRequestsPerChild为0,即使您的数据库不在同一物理服务器上,服务器资源也可能会被淹没。

基本上,对于Web服务器性能,您不希望进行交换。运行测试,然后立即使用以下命令检查Web服务器上的内存:

free -m

这将为您提供MB和交换使用的内存使用量。理想情况下,您应该看到交换0或接近0.如果不是zilch或非常低的交换使用,问题只是内存耗尽而您的服务器正在颠簸因此浪费CPU导致响应时间变慢。

你需要确定一些数字,但首先做一个'顶部'并按下Shift-M而top运行以按内存排序。下次运行测试并找到每个httpd进程报告的MEM%%的球场数。它会有所不同,所以最好使用较高的那些作为最坏情况约束的指南。我在同一台服务器上有一个wordpress,一个drupal和一个客户站点,每个http进程从一开始就经常分配20M,并最终在时间上升 - 如果未经检查超过100M。

从我的屁股中取出一些数字,例如,如果我有2G和Linux,核心服务和mysql使用800M,我会保留对内存的期望我想要为Apache乐趣在1G以下。有了这个,如果我的apache进程在高端平均使用20M,我只能有50个MaxClients。这是一个非常不保守的数字,在现实生活中我会将Max降到40左右以保证安全。不要试图捏住内存...如果你正在提供足够的流量来同时拥有40个连接,那么在加入Max服务器之前,要花费100美元去4G。这是其中之一,一旦你越线,一切都在马桶上,所以安全地保持在你的记忆限制之下!

另外,使用php我喜欢将MaxRequestsPerChild保持在100左右......你不是CPU绑定服务网页,所以不要担心会产生几毫秒来产生新的子进程。将其设置为0意味着无限请求,除非总客户端超过MaxSpareServers,否则它们永远不会被终止。这通常是一个非常糟糕的事情与php使用apache工作者,因为他们只是继续增长直到出现问题(比如必须硬重启你的服务器,因为你无法登录因为apache耗尽所有内存和没有超时,ssh无法工作。)

祝你好运!

答案 1 :(得分:1)

在下载之前加载的完全页数是多少?您提到您正在从单个外部脚本创建65个并发请求。您没有启用类似limitipconn的mod,它会限制来自单个IP或其他内容的N个连接后的内容?它总是正好是30(或其他)连接然后延迟吗?