我正在使用以下命令ab
对Apache/2.2.3 (prefork) 进行基准测试:siege
ab -kc 200 -t 120 http://www.mywebsite.com/test.php
siege -c200 -t2M http://www.mywebsite.com/test.php
test.php 是一个非常简单的文件,它只创建一个 mysql 连接然后关闭
<?php
$link = mysql_connect("localhost", "username", "password");
mysql_select_db("dbname");
if(!$link) {
die('Could not connect: ' . mysql_error());
}
echo 'Connected successfully';
mysql_close($link);
?>
我得到的结果大量失败的请求在他们中。我正在尝试弄清楚如何减少这些失败请求的数量因为这是一个相当简单的脚本,服务器负载很低,所以在具有 8G RAM 的四核 Xeon 3Ghz 机器上应该不会遇到问题。
输出自围城
Transactions: 9438 hits
Availability: 98.33 %
Elapsed time: 119.39 secs
Data transferred: 0.38 MB
Response time: 1.31 secs
Transaction rate: 79.05 trans/sec
Throughput: 0.00 MB/sec
Concurrency: 103.37
Successful transactions 9438
Failed transactions: 160
Longest transaction: 21.24
Shortest transaction 0.21
输出自AB:
Benchmarking www.mywebsite.com (be patient)
Server Software: Apache/2.2.3
Server Hostname: www.mywebsite.com
Server Port: 80
Document Path: /test.php
Document Length: 22 bytes
Concurrency Level: 200
Time taken for tests: 35.851520 seconds
Complete requests: 50000
Failed requests: 618
(Connect: 0, Length: 618, Exceptions: 0)
Write errors: 0
Keep-Alive requests: 49600
Total transferred: 12932098 bytes
HTML transferred: 1149345 bytes
Requests per second: 1394.64 [#/sec] (mean)
Time per request: 143.406 [ms] (mean)
Time per request: 0.717 [ms] (mean, across all concurrent requests)
Transfer rate: 352.26 [Kbytes/sec] received
快速介绍一下我的 Apache 配置
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
<IfModule prefork.c>
StartServers 20
MinSpareServers 20
MaxSpareServers 50
ServerLimit 500
#default 200
MaxClients 500
MaxRequestsPerChild 4000
</IfModule>
我在另一台性能较弱的服务器上用相同的脚本运行了相同的测试,没有出现任何失败请求,而且测试完成得更快。所以我想知道这台服务器出了什么问题。
更新的 MySQL 配置:
变量
mysql> show variables LIKE '%connect%';
+--------------------------+-------------------+
| Variable_name | Value |
+--------------------------+-------------------+
| character_set_connection | latin1 |
| collation_connection | latin1_swedish_ci |
| connect_timeout | 10 |
| init_connect | |
| max_connect_errors | 10 |
| max_connections | 100 |
| max_user_connections | 0 |
+--------------------------+-------------------+
全球地位
mysql> SHOW GLOBAL STATUS LIKE '%connect%';
+--------------------------+---------+
| Variable_name | Value |
+--------------------------+---------+
| Aborted_connects | 343 |
| Connections | 1463797 |
| Max_used_connections | 101 |
| Ssl_client_connects | 0 |
| Ssl_connect_renegotiates | 0 |
| Ssl_finished_connects | 0 |
| Threads_connected | 3 |
+--------------------------+---------+
答案1
您的并发限制肯定是在 MySQL 方面,尽管我不确定这对实际性能来说一定是件坏事。您让 MySQL 接受 100 个同时连接,因此最多只能同时有 100 个 Apache 实例与其通信。由于您的测试脚本非常简单,它将花费大部分时间处于活动状态,或至少连接到 MySQL。为处于其他状态的 Apache 进程添加更多内容,您的并发率将达到 100。我不确定 ab 为何获得更高的 200 并发级别,但也许它以不同的方式计算。
如果您希望获得更高的基准数字,只需将 MySQL 的连接限制设置得更高即可。MySQL 连接限制可能至少应等于花费大部分时间与数据库通信的 Apache 进程数。
答案2
不幸的是,使用 ab 您实际上是在对客户端性能进行基准测试。您需要一些更好的性能工具,例如 httperf,它不会杀死客户端主机。如果您想运行真正的测试,您应该使用多于 1 个主机,或者在某些情况下,siege 也是一个不错的工具。只需检查 ab 实际上在做什么,它可能会遇到打开文件限制的问题。检查服务器配置也很有用。
答案3
也许 MySQL 方面出了什么问题。在这种快速的“创建数据库连接 - 关闭它”测试中,很容易发生的一件事是 mysql_max_connection_errors 填满了,默认情况下它只有 10。
还有一件事:您是否已经检查过较弱(但可以工作)的服务器和较快(但不工作)的服务器之间的最大连接限制是否相等?也许 100 个同时 MySQL 连接的默认值已经满了。