我很好奇为什么在使用ab
和-c 7(7个并发线程)对Python Web服务器CherryPy进行基准测试时,它可以处理1500个请求/秒(大约是我的期望),但是当我更改为-c 8时,它下降到25个请求/秒.我在numthreads = 10上运行CherryPy(但如果我使用numthreads = 8或20则没有什么不同)在具有四个运行Python 2.6的64位Windows机器上.
我半怀疑Python GIL是问题的一部分,但是我不知道为什么只有当我有多达8个并发请求线程时才会发生.在四核计算机上,我希望它可能会在-c 4处更改,但事实并非如此.
我正在使用web.py随附的单文件CherryPy Web服务器,这是我要针对其进行测试的WSGI应用程序:
from web.wsgiserver import CherryPyWSGIServer
def application(environ, start_response):
start_response("200 OK", [("Content-type", "text/plain")])
return ["Hello World!",]
server = CherryPyWSGIServer(('0.0.0.0', 80), application, numthreads=10)
try:
server.start()
except KeyboardInterrupt:
server.stop()
7个和8个并发线程的ab输出为:
C:\\> ab -n 1000 -c 7 http://localhost/
...
Concurrency Level: 7
Time taken for tests: 0.670 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 130000 bytes
HTML transferred: 12000 bytes
Requests per second: 1492.39 [#/sec] (mean)
Time per request: 4.690 [ms] (mean)
Time per request: 0.670 [ms] (mean, across all concurrent requests)
Transfer rate: 189.46 [Kbytes/sec] received
C:\\> ab -n 1000 -c 8 http://localhost/
...
Concurrency Level: 8
Time taken for tests: 7.169 seconds
Complete requests: 158
Failed requests: 0
Write errors: 0
Total transferred: 20540 bytes
HTML transferred: 1896 bytes
Requests per second: 22.04 [#/sec] (mean)
Time per request: 362.973 [ms] (mean)
Time per request: 45.372 [ms] (mean, across all concurrent requests)
Transfer rate: 2.80 [Kbytes/sec] received
解决方法:
在我的linux机器上,这是由于从ab重传了TCP数据包,尽管我不确定为什么:
No. Time Source Destination Protocol Info Delta
10682 21.218156 127.0.0.1 127.0.0.1 TCP http-alt > 57246 [SYN, ACK] Seq=0 Ack=0 Win=32768 Len=0 MSS=16396 TSV=17307504 TSER=17306704 WS=6 21.218156
10683 21.218205 127.0.0.1 127.0.0.1 TCP 57246 > http-alt [ACK] Seq=82 Ack=1 Win=513 Len=0 TSV=17307504 TSER=17307504 SLE=0 SRE=1 0.000049
10701 29.306438 127.0.0.1 127.0.0.1 HTTP [TCP Retransmission] GET / HTTP/1.0 8.088233
10703 29.306536 127.0.0.1 127.0.0.1 TCP http-alt > 57246 [ACK] Seq=1 Ack=82 Win=512 Len=0 TSV=17309526 TSER=17309526 0.000098
10704 29.308555 127.0.0.1 127.0.0.1 TCP [TCP segment of a reassembled PDU] 0.002019
10705 29.308628 127.0.0.1 127.0.0.1 TCP 57246 > http-alt [ACK] Seq=82 Ack=107 Win=513 Len=0 TSV=17309526 TSER=17309526 0.000073
10707 29.309718 127.0.0.1 127.0.0.1 TCP [TCP segment of a reassembled PDU] 0.001090
10708 29.309754 127.0.0.1 127.0.0.1 TCP 57246 > http-alt [ACK] Seq=82 Ack=119 Win=513 Len=0 TSV=17309526 TSER=17309526 0.000036
10710 29.309992 127.0.0.1 127.0.0.1 HTTP HTTP/1.1 200 OK (text/plain) 0.000238
10711 29.310572 127.0.0.1 127.0.0.1 TCP 57246 > http-alt [FIN, ACK] Seq=82 Ack=120 Win=513 Len=0 TSV=17309527 TSER=17309526 0.000580
10712 29.310661 127.0.0.1 127.0.0.1 TCP http-alt > 57246 [ACK] Seq=120 Ack=83 Win=512 Len=0 TSV=17309527 TSER=17309527 0.000089
Wireshark也没有拾取原始的“ GET”数据包.由于某种原因,即使TCP连接是双AC的,ab也会尝试发送请求并失败.然后,客户端的TCP堆栈会等待几秒钟,以等待从未发送过的数据包进行ACK,然后,如果它没有看到ACK,则重试并成功.
就个人而言,我不会为此担心.如果有问题,那不是CherryPy的问题.它可能与ab的内部结构,使用HTTP / 1.0而不是1.1,缺少keepalive,使用localhost而不是实际的套接字(模拟某些网络流量的现实并忽略其他现实), Windows(眨眼),同一接口上的其他流量,在CPU上加载…列表不断.