自定义 CMS 上的 Apache Bench 结果很糟糕

发布于 2024-12-06 22:47:03 字数 2081 浏览 2 评论 0原文

请注意:这不是对劣质 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)

网站运行良好,没有检测到问题,Google 的网站管理员工具报告我们的网站比 80% 的页面快,我认为这很好。

测试是:

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

也许是某种 Apache 问题? .htaccess 配置错误或类似?

更新:

刚刚使用套接字进行了简单的测试,结果相似。页面加载非常非常慢。如果我在另一个网站上运行我的脚本,一切都很好。

另外,还有一个关于块长度问题的小提示。 (错误的 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/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)

您注意到任何异常情况吗?

Please note: This is not a complain about a shoddy CMS.

Just toying with Apache Bench and got terrible results with our custom CMS, more exactly i got:

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

When i run another test with a plain php file i got:

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

Another test with a previous version of the CMS:

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

The website(s) are working fine, no problems detected, Google's Webmaster Tools reports our sites as faster than 80% of the pages which is fine, i think.

The test was:

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

Maybe some kind of Apache problem? Bad .htaccess config, or similar?

Update:

Just ran a simple test with sockets and the results are similar. Page loads very, very slowly. If i ran my script with another website everything is fine.

Also, there's a small hint about a chunk length problem. (Bad Apache Headers, or line endings?)

The site is gzipped, and when verbose logging turned on, i see these lines in the response:

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

Always at the same place, in the middle of the HTML-source, then <!DOCTYPE HTML> again.

Please, help.

Update #2:

Just checked my HTTP headers with Rex Swain's HTTP Viewer and got these results:

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)

Do you notice anything unusual?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

南冥有猫 2024-12-13 22:47:03

如果它与普通 Web 浏览器配合良好(正如您在评论中提到的),CMS 会以不同的方式处理来自 Apache Benchmark 的请求。

快速检查表:

  • AFAIK Apache Benchmark 仅发送简单请求,无需任何 cookie 处理,因此请尝试使用有效的 cookie 设置 -C (从 Web 浏览器复制值)。
  • 尝试将与 Web 浏览器发送的标头完全相同的标头发送到 CMS。使用 netcat、HttpFox 或数据包嗅探器保存有效请求的转储,并使用 -H 设置丢失的标头。
  • 当您使用 Apache Benchmark 向服务器发送请求时,对服务器上的 CMS 进行分析。也许你发现了瓶颈。两个穷人的 error_log 调用,第一个和最后一个都有时间戳index.php 行(或测试脚本的入口点)可以显示 PHP 脚本的速度,并有助于计算 Apache HTTP 服务器和网络的开销。
  • 如果您从不同的机器运行套接字测试和浏览器测试,则可能是 DNS 问题(关闭 Apache 中的 HostnameLookups)。尝试在同一台机器上运行它们。
  • 尝试 ab -k ...ab -H "Connection: close" ...

我猜想 CMS 在初始化会话时会执行一些成本高昂的初始化,并且在处理第一个请求时会发生这种情况。由于 Apache Benchmark 不会将 cookie 发送回 CMS,因此它会为每个请求创建一个新会话,这也是导致响应缓慢的原因。

第二个猜测是 CMS 以不同的方式处理传入的 http 标头,并且 Apache Benchmark 发送的标头(或缺少标头)会触发一些昂贵/缓慢的处理。自从谷歌网站管理员工具的报告以来,它看起来更合适。


Apache Benchmark 发送 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 文件的同一服务器上运行良好。无论如何,您可以通过使用保持活动连接(-k)来解决它:

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

或显式禁用持久连接:

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

但这仍然是服务器端问题和您原来的ab命令是对的。

请注意,此错误可能仅影响 HTTP 1.0 客户端(如 Apache Benchmark、wget),使用常规浏览器的客户端不会注意到它。

If it works well with ordinary web browsers (as you mentioned in the comments) the CMS handle the requests from Apache Benchmark differently.

A quick checklist:

  • AFAIK Apache Benchmark just send simple requests without any cookie handling, so try to set -C with a valid cookie (copy the values from a web browser).
  • Try to send exactly the same headers to the CMS as the web browser sends. Save a dump of a valid request with netcat, HttpFox or a packet sniffer and set the missing headers with -H.
  • Profile the CMS on the server while you're sending to it a request with Apache Benchmark. Maybe you found the bottleneck. Two poor man's error_log calls with a timestamp in the first and the last line of the index.php (or the tested script's entry point) could show how fast is the PHP script and help to calculate the overhead of the Apache HTTP Server and network.
  • If you run socket tests and browser tests from different machines it's could be a DNS issue (turn off HostnameLookups in Apache). Try to run them from the same machine.
  • Try ab -k ... or ab -H "Connection: close" ....

I guess the CMS does some costly initialization when it initializes the session and it's happens when it processes the first request. Since Apache Benchmark does not send the cookies back the CMS it creates a new session for every request and it's the cause of the slow answers.

A second guess is that the CMS handle the incoming http headers differently and the headers which was sent (or the lack of them) by Apache Benchmark trigger some costly/slow processing. It looks more appropriate since the report of the Google's Webmaster Tools.


Apache Benchmark sends HTTP 1.0 request, for example:

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

It looks to me that your server does not send any http header about Keep-Alive settings but it assumes that the client uses keep-alive when the client uses HTTP 1.0. It's not an RFC compliant behaviour:

From RFC 2616, 19.6.2 Compatibility with HTTP/1.0 Persistent Connections:

Some clients and servers might wish to be compatible with some
previous implementations of persistent connections in HTTP/1.0
clients and servers. Persistent connections in HTTP/1.0 are
explicitly negotiated as they are not the default behavior.

By default Apache Benchmark doesn't use keep-alive so it waits when the response arrives for the closing of the socket. The server closes it after 15 seconds idle. Downloading the main page with wget also takes 15 seconds. Wget also uses HTTP 1.0 in the request.

I think it's a bug in the PHP code of the CMS since ab works well on the same server with a plain php file. Anyway, you can workaround it with using keep-alive connections (-k):

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

or with explicitly disabling persistent connections:

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

but it's still a server side issue and your original ab commands is right.

Please note that this bug probably affects only HTTP 1.0 clients (like Apache Benchmark, wget) and clients with regular browsers will not notice it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文