自定义CMS的Apache Bench测试结果很差

4
请注意:这不是对一个劣质CMS的抱怨。
我刚刚在使用Apache Bench时测试了我们自定义的CMS,结果非常糟糕,具体来说,我得到了:
Requests per second:    0.37 [#/sec] (mean)

当我使用一个普通的PHP文件运行另一个测试时,我得到了以下结果:
Requests per second:    4786.07 [#/sec] (mean)

使用 CMS 先前版本进行的另一个测试:

Requests per second:    6068.66 [#/sec] (mean)

网站运行良好,未检测到任何问题,谷歌的Webmaster工具报告我们的网站速度比80%的页面更快,这很好。

测试内容如下:

ab -t 30 -c 10 http://example.com/

也许是Apache的问题?可能是.htaccess配置或类似的问题?
更新:
刚刚使用sockets进行了简单测试,结果类似。页面加载非常慢。如果我在另一个网站上运行我的脚本,一切都很好。
此外,有一个小提示关于块长度问题。(糟糕的Apache标头或行尾?)
该网站已经压缩,并且当打开详细日志记录时,我可以在响应中看到这些行:
LOG: Response code = 200
LOG: header received:
HTTP/1.1 200 OK
Date: Tue, 04 Oct 2011 13:10:49 GMT
Server: Apache
Set-Cookie: PHPSESSID=ibnfoqir9fee2koirfl5mhm633; path=/
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Cache-Control: post-check=0, pre-check=0
Vary: Accept-Encoding
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

2ef6

始终位于HTML源代码中间的同一位置,然后再次出现<!DOCTYPE HTML>

请帮忙。

更新 #2:

使用Rex Swain的HTTP查看器检查了我的HTTP头,并获得了以下结果:

HTTP/1.1·200·OK(CR)(LF)
Date:·Wed,·05·Oct·2011·08:33:51·GMT(CR)(LF)
Server:·Apache(CR)(LF)
Set-Cookie:·PHPSESSID=n88g3qcvv9p6irm1fo0qfse8m2;·path=/(CR)(LF)
Expires:·Sat,·26·Jul·1997·05:00:00·GMT(CR)(LF)
Cache-Control:·no-store,·no-cache,·must-revalidate(CR)(LF)
Pragma:·no-cache(CR)(LF)
Cache-Control:·post-check=0,·pre-check=0(CR)(LF)
Vary:·Accept-Encoding(CR)(LF)
Connection:·close(CR)(LF)
Transfer-Encoding:·chunked(CR)(LF)
Content-Type:·text/html;·charset=UTF-8(CR)(LF)
(CR)(LF)

你注意到了什么不寻常的吗?


你有检查服务器和CMS的日志吗? - palacsint
你可能首先要检查问题是来自客户端还是服务器端。然后通过二分法的方法来隔离问题,以便找出主要问题。 - hornetbzz
@palacsint 日志没问题,一切正常。 - fabrik
@hornetbzz 当我在浏览器中打开网站时,一切正常(没有任何表现出弱性能的迹象)。但是运行Apachebench(相同的服务器或其他服务器,没有区别)或通过简单的套接字测试进行访问,则结果非常糟糕。 - fabrik
1个回答

4
如果它在普通的网络浏览器上运行良好(如您在评论中提到的),CMS将以不同的方式处理Apache基准测试的请求。
一个快速的检查清单:
  • 据我所知,Apache Benchmark 只发送简单的请求而没有任何 cookie 处理,因此请尝试使用有效的 cookie 设置 -C(从 Web 浏览器复制值)。
  • 尝试向 CMS 发送与 Web 浏览器相同的标头。使用 netcat、HttpFox 或数据包嗅探器保存有效请求的转储,并使用 -H 设置缺少的标头。
  • 在向 CMS 发送 Apache Benchmark 请求时,在服务器上对 CMS 进行分析。也许你能找到瓶颈所在。在 index.php(或测试脚本入口点)的第一行和最后一行中带有时间戳的两个 error_log 调用可以显示 PHP 脚本的运行速度并帮助计算 Apache HTTP Server 和网络的开销。
  • 如果你从不同的机器上运行套接字测试和浏览器测试,则可能存在 DNS 问题(在 Apache 中关闭 HostnameLookups)。尝试从同一台机器上运行它们。
  • 尝试使用 ab -k ...ab -H "Connection: close" ...
我猜测CMS在初始化会话时进行了一些昂贵的初始化操作,这发生在处理第一个请求时。由于Apache Benchmark没有将cookie发送回CMS,因此它为每个请求创建一个新会话,这是缓慢响应的原因。
第二个猜测是CMS以不同的方式处理传入的HTTP头,并且Apache Benchmark发送的头触发了一些昂贵/缓慢的处理。这似乎更适合Google的Webmaster工具报告。

Apache基准测试发送HTTP 1.0请求,例如:

GET / HTTP/1.0
Host: localhost:9100
User-Agent: ApacheBench/2.3
Accept: */*

我觉得你的服务器没有发送关于Keep-Alive设置的任何http头,但是它假设客户端在使用HTTP 1.0时使用keep-alive。这不是符合RFC的行为:

从《RFC 2616, 19.6.2 兼容HTTP/1.0持久连接》中可以看出:

一些客户端和服务器可能希望与先前实现的HTTP/1.0持久连接兼容的某些客户端和服务器。HTTP/1.0中的持久连接是明确协商的,因为它们不是默认行为。

默认情况下,Apache Benchmark不使用keep-alive,因此在响应到达并关闭套接字之前等待。服务器在15秒闲置后关闭它。使用wget下载主页面也需要15秒。Wget还在请求中使用HTTP 1.0。

我认为这是CMS PHP代码中的一个错误,因为'ab'在同一台服务器上与纯PHP文件良好地工作。无论如何,您可以使用keep-alive连接(-k)解决它:
ab -k -t 30 -c 10 http://example.com/

或者明确禁用持久连接:

ab -H "Connection: close" -t 30 -c 10 http://example.com/

但这仍然是服务器端的问题,你原来的ab命令是正确的。

请注意,这个bug可能只影响HTTP 1.0客户端(例如Apache Benchmark,wget),而使用普通浏览器的客户端不会注意到它。


尝试了两种方法,但不幸的是都没有成功。只能得到更少的 RPS(0.07/sec)。 - fabrik
展示来自浏览器的原始请求和Apache基准测试的参数。可能只是一个打字错误。请检查更新。 - palacsint
尝试使用 ab -k。我不知道为什么它如此快(但是)。 - palacsint
第一个测试失败了,出现“失败10次后中止测试”的情况,但第二个测试达到了每秒223个请求数。这是Apachebench的解决方法吗?顺便问一下,我的代码里还有些bug吗? - fabrik
这绝对是CMS源代码中的一个错误(而不是PHP或Apache的错误)。我刚刚注意到“ab”可以在同一台服务器上与普通的PHP脚本很好地配合使用。(我也更新了答案。) - palacsint
显示剩余8条评论

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