使用AB对Nginx压测和并发预估
简介
ab命令会创建多个并发访问线程,模拟多个访问者同时对某一URL地址进行访问。它的测试目标是基于URL的;
# 1.ab每次只能测试一个URL,适合做重复压力测试
# 2.参数很多,可以支持添加cookie,启用keeplive
# 3.可以将测试结果导入文件
# 4.设置显示信息的详细程度
综合来说,适合单个URL的测试,可以支持更多方式去测试,比如使用cookie模仿用户提交表单来测试数据库,但ab是单线程的,不适合测性能高的服务器;
安装ab
需要安装httpd-tools
yum -y install httpd-tools
使用案例
Example1
ab -c 1000 -n 10000 http://192.168.2.38/
# -c指定1000并发,-n指定总10000次,相当于1000个人访问10次。
# -k 是否开启长连接
Server Software: nginx/1.8.1 #服务器信息和版本
Server Hostname: 192.168.2.38 #服务器的域名
Server Port: 80 #端口
Document Path: / #访问的路径
Document Length: 612 bytes #文档的大小为 612 bytes(此为http响应的正文长度)
Concurrency Level: 1000 #并发请求数
Time taken for tests: 0.287 seconds #整个测试持续的时间,默认秒
Complete requests: 1000 #完成的请求数
Failed requests: 0 #失败的请求书
Write errors: 0 #网络连接写入错误数
Total transferred: 844000 bytes #传输的总数据量
HTML transferred: 612000 bytes #传输的HTML内容传输量
Requests per second: 3485.11 [#/sec] (mean) #平均每秒请求数
Time per request: 286.935 [ms] (mean) #所有用户都请求一次的平均时间
Time per request: 0.287 [ms] (mean, across all concurrent requests) #单个用户请求一次的时间
Transfer rate: 2872.49 [Kbytes/sec] received #传输速率
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 84 4.1 84 94
Processing: 86 99 6.6 100 109
Waiting: 0 83 16.2 84 108
Total: 95 183 7.4 182 195
#所有服务请求的百分比占用时间,这里50%的请求用时182ms,一般看90%的部分
Percentage of the requests served within a certain time (ms)
50% 182
66% 188
75% 191
80% 192
90% 193
95% 194
98% 194
99% 194
100% 195 (longest request)
可能会报错
apr_socket_recv: Connection reset by peer (104)
Total of 29969 requests completed
连接被重置,bingyi了以下,apr_socket_recv这个是操作系统内核的一个参数,在高并发的情况下,内核会认为系统受到了SYN flood攻击,会发送cookies(possible SYN flooding on port 80. Sending cookies),这样会减慢影响请求的速度,所以在应用服务武器上设置下这个参数为0禁用系统保护就可以进行大并发测试了;
然后就可以超过1000个并发测试了,但是ab只支持
# vim /etc/sysctl.conf
net.ipv4.tcp_syncookies = 0
# sysctl -p
接下来是每秒访问,因为ab不支持每秒访问多少,所以写一个脚本
#!/bin/bash
#当下是运行60秒,每秒1000并发,可以观察服务器负载
for i in `seq 1 60`
do
ab -c 1000 -n 1000 http://192.168.2.38/ &
sleep 1
done
Example2(使用cookie模拟多用户)
1.使用cookie来模拟多个用户访问
先用账户和密码登录后,用开发者工具找到标识这个会话的Cookie值(Session ID)记下来
# 一个
ab -n 100 -C key=value http://test.com/
# 多个账号
ab -n 100 -H “Cookie: Key1=Value1; Key2=Value2” http://test.com/
具体参数
-n 即requests,用于指定压力测试总共的执行次数。
-c 即concurrency,用于指定压力测试的并发数。
-t 即timelimit,等待响应的最大时间(单位:秒)。
-b 即windowsize,TCP发送/接收的缓冲大小(单位:字节)。
-p 即postfile,发送POST请求时需要上传的文件,此外还必须设置-T参数。
-u 即putfile,发送PUT请求时需要上传的文件,此外还必须设置-T参数。
-T 即content-type,用于设置Content-Type请求头信息,例如:application/x-www-form
-urlencoded,默认值为text/plain。
-v 即verbosity,指定打印帮助信息的冗余级别。
-w 以HTML表格形式打印结果。
-i 使用HEAD请求代替GET请求。
-x 插入字符串作为table标签的属性。
-y 插入字符串作为tr标签的属性。
-z 插入字符串作为td标签的属性。
-C 添加cookie信息,例如:"Apache=1234"(可以重复该参数选项以添加多个)。
-H 添加任意的请求头,例如:"Accept-Encoding: gzip",请求头将会添加在现有的多个请求头之后(可以重复该参数选项以添加多个)。
-A 添加一个基本的网络认证信息,用户名和密码之间用英文冒号隔开。
-P 添加一个基本的代理认证信息,用户名和密码之间用英文冒号隔开。
-X 指定使用的代理服务器和端口号,例如:"126.10.10.3:88"。
-V 打印版本号并退出。
-k 使用HTTP的KeepAlive特性。
-k 使用HTTP的KeepAlive特性。
-d 不显示百分比。
-S 不显示预估和警告信息。
-g 输出结果信息到gnuplot格式的文件中。
-e 输出结果信息到CSV格式的文件中。
-r 指定接收到错误信息时不退出程序。
-h 显示用法信息,其实就是ab -help。
Nginx压测和并发预估
预估算法: { (?G) * 1024 - system} / 请求大小
#(?G):表示内存大小
# 1024:表示内存容量标准进制
# system:表示系统和服务占用的额外内存和需要预留的内存
# 请求大小:表示静态(一般为KB)或动态(一般为MB)的请求大小
# 16核32G服务器,可以抗住4万多用于负载均衡的并发,最多可以抗住5-6万
简单使用下ab压测工具
ab -n2000 -c2 http://127.0.0.1/index.html # -n 总的请求次数# -c 并发请求数# -k 是否开启长连接Server Software: nginx/1.12.2 Server Hostname: 127.0.0.1 Server Port: 80Document Path: /index.htmlDocument Length: 19 bytes #页面长度Concurrency Level: 200Time taken for tests: 1.013 seconds # 总花费总时长Complete requests: 2000 # 总请求数Failed requests: 0 # 请求失败数Write errors: 0Total transferred: 510000 bytes # 总共传输字节数,包含http的头信息等HTML transferred: 38000 bytes # html字节数,实际的页面传递字节数Requests per second: 9333.23 [#/sec] (mean) # 每秒多少请求/s(总请求出/总共完成的时间)Time per request: 101.315 [ms] (mean) # 客户端访问服务端, 单个请求所需花费的时间Time per request: 0.507 [ms] (mean, across all concurrent requests) # 服务端处理请求的时间Transfer rate: 491.58 [Kbytes/sec] received # 判断网络传输速率, 观察网络是否存在瓶颈 [root@node-a ~]# ab -c 20000 -n 80000 http://1.1.1.1/index.htmlThis is ApacheBench, Version 2.3 <$Revision: 1430300 $>Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking 1.1.1.1 (be patient)Completed 8000 requestsCompleted 16000 requestsCompleted 24000 requestsCompleted 32000 requestsCompleted 40000 requestsCompleted 48000 requestsCompleted 56000 requestsCompleted 64000 requestsCompleted 72000 requestsCompleted 80000 requestsFinished 80000 requestsServer Software: nginx/1.16.0 # 服务器信息和版本Server Hostname: 1.1.1.1 # 服务器的域名Server Port: 80 # 端口Document Path: /index.html # 访问路径Document Length: 612 bytes # 文档大小 612bytes (此为http响应的正文长度)Concurrency Level: 20000 # 并发请求数Time taken for tests: 3.735 seconds # 整个测试持续时间,默认秒Complete requests: 80000 # 完成请求数Failed requests: 1 # 失败请求数(Connect: 0, Receive: 0, Length: 1, Exceptions: 0)Write errors: 0 # 网络连接写入错误数Non-2xx responses: 1Total transferred: 67599494 bytes # 传输总数据量HTML transferred: 48959565 bytes # 传输HTML内容传输量Requests per second: 21418.17 [#/sec] (mean) # 每秒多少请求,这个是非常重要的参数数值,服务器的吞吐量Time per request: 933.787 [ms] (mean) # 所有用户请求一次的平均时间Time per request: 0.047 [ms] (mean, across all concurrent requests) # 服务器平均处理时间,也就是服务器吞吐量的倒数Transfer rate: 17674.04 [Kbytes/sec] received # 传输速率Connection Times (ms) min mean[+/-sd] median maxConnect: 0 171 573.6 7 3022Processing: 2 15 30.6 10 807Waiting: 1 12 30.1 8 805Total: 5 186 583.0 18 3437Percentage of the requests served within a certain time (ms) 50% 18 # 50%的请求在183ms内返回 66% 20 75% 25 80% 30 90% 455 95% 1037 98% 3031 99% 3041 100% 3437 (longest request)
查看并发连接数和连接状态
查看Web服务器(Nginx Apache)的并发请求数及其TCP连接状态
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"t",state[key]}'
返回结果一般如下
# LAST_ACK 5 (正在等待处理的请求数)# SYN_RECV 30# ESTABLISHED 1597 (正常数据传输状态)# FIN_WAIT1 51# FIN_WAIT2 504# TIME_WAIT 1057 (处理完毕,等待超时结束的请求数)
其他参数说明
# CLOSED:无连接是活动的或正在进行
# LISTEN:服务器在等待进入呼叫
# SYN_RECV:一个连接请求已经到达,等待确认
# SYN_SENT:应用已经开始,打开一个连接
# ESTABLISHED:正常数据传输状态
# FIN_WAIT1:应用说它已经完成
# FIN_WAIT2:另一边已同意释放
# ITMED_WAIT:等待所有分组死掉
# CLOSING:两边同时尝试关闭
# TIME_WAIT:另一边已初始化一个释放
# LAST_ACK:等待所有分组死掉
查看Nginx和Apache的运行进程数
ps -ef | grep nginx | wc -l
ps -ef | grep httpd | wc -l
查看Web服务器进程连接数
netstat -antp | grep 80 | grep ESTABLISHED -c
优化案例(8c16g)
优化前
服务器配置(8c16g)
- time用于计时
- dd用于复制,从if读出,写到of;
- if=/dev/zero不产生IO,因此可以用来测试纯写速度;同理of=/dev/null不产生IO,可以用来测试纯读速度。
- bs是每次读或写的大小,即一个块的大小,count是读写块的数量,相乘就是读写数据量大小;
数据量越大越准确,多次测试取平均值;
开启nginx的status模块
# 在 nginx.conf 中配置统计模块
location /status{
# 开启状态
stub_status on;
# 不需要日志
access_log off;
# 只允许此 ip 访问
allow 192.168.222.101;
# 其他 ip 禁止访问
deny all;
}
也可以使用Webbench压测,下面仅供参考
ab压测信息
[root@node-a ~]# ab -c 20000 -n 100000 http://1.1.1.1/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 1.1.1.1 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software: nginx/1.16.0
Server Hostname: 1.1.1.1
Server Port: 80
Document Path: /index.html
Document Length: 612 bytes
Concurrency Level: 20000
Time taken for tests: 64.315 seconds
Complete requests: 100000
Failed requests: 5
(Connect: 0, Receive: 0, Length: 5, Exceptions: 0)
Write errors: 0
Non-2xx responses: 2
Total transferred: 84496453 bytes
HTML transferred: 61197294 bytes
Requests per second: 1554.84 [#/sec] (mean)
Time per request: 12863.025 [ms] (mean)
Time per request: 0.643 [ms] (mean, across all concurrent requests)
Transfer rate: 1283.00 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 118 473.7 6 3018
Processing: 2 14 330.5 9 60001
Waiting: 0 10 35.5 7 1612
Total: 4 132 583.7 15 60001
Percentage of the requests served within a certain time (ms)
50% 15
66% 18
75% 19
80% 20
90% 25
95% 1018
98% 3018
99% 3024
100% 60001 (longest request)
优化后
每个请求都需要建立 socket 连接,那么影响并发量的因素之一;
客户端不允许一次性创建过多的连接
服务端不允许一次性创建过多的连接
每个请求都要访问一些资源,那么影响并发量的因素之一:
服务端不允许一个文件在同一时间点被访问 N 次,相当于一个文件在服务端打开 N 次
我们在使用 ab 模拟并发访问后,执行 dmesg 命令,查看请求的信息
dmesg
# 执行结果的最后一行为:possible SYN flooding on port 80. Sending cookies.
# 解释:在同一时间有过多的请求访问 80 端口,导致系统误认为遭受了洪水攻击
从上面的优化分析中,我们可以从 socket 和文件两个层面进行 Nginx 的高并发优化
socket:分为系统层面和 nginx 层面:
系统层面
# 禁止洪水抵御,这个操作在重启之后失效
命令:more /proc/sys/net/ipv4/tcp_syncookies
结果:1
命令:echo 0 > /proc/sys/net/ipv4/tcp_syncookies
# 最大连接数,这个操作在重启之后失效
命令:more /proc/sys/net/core/somaxconn
结果:128
命令:echo 50000 > /proc/sys/net/core/somaxconn
# 加快 tcp 连接的回收,这个操作在重启之后失效
命令:cat /proc/sys/net/ipv4/tcp_tw_recycle
结果:0
命令:echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
# 使空的 tcp 连接重新被利用,这个操作在重启之后失效
命令:cat /proc/sys/net/ipv4/tcp_tw_reuse
结果:0
命令:echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
# 完整的命令
echo 50000 > /proc/sys/net/core/somaxconn
echo 0 > /proc/sys/net/ipv4/tcp_syncookies
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
sysctl -w net.ipv4.tcp_timestamps=1 开启对于TCP时间戳的支持,若该项设置为0,则下面一项设置不起作用
sysctl -w net.ipv4.tcp_tw_recycle=1
vm.max_map_count = 262144
再次压测nginx
[root@node-a ~]# ab -c 20000 -n 100000 http://1.1.1.1/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 1.1.1.1 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software: nginx/1.16.0
Server Hostname: 1.1.1.1
Server Port: 80
Document Path: /index.html
Document Length: 612 bytes
Concurrency Level: 20000
Time taken for tests: 4.690 seconds
Complete requests: 100000
Failed requests: 1
(Connect: 0, Receive: 0, Length: 1, Exceptions: 0)
Write errors: 0
Non-2xx responses: 1
Total transferred: 84499494 bytes
HTML transferred: 61199565 bytes
Requests per second: 21320.91 [#/sec] (mean)
Time per request: 938.046 [ms] (mean)
Time per request: 0.047 [ms] (mean, across all concurrent requests)
Transfer rate: 17593.81 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 140 485.5 6 3020
Processing: 2 14 47.0 9 1604
Waiting: 0 12 46.9 7 1604
Total: 2 154 499.6 16 4619
Percentage of the requests served within a certain time (ms)
50% 16
66% 20
75% 22
80% 25
90% 411
95% 1023
98% 3018
99% 3027
100% 4619 (longest request)
nginx
# 子进程允许打开的连接数(nginx.conf)及 IO 选择
events {
worker_processes 8;
# 子进程连接数
worker_connections 65535;
# 使用 linux 下的多路复用 IO,是 poll 增强版本
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
#sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
client_header_timeout 60;
client_body_timeout 60;
reset_timedout_connection on;
send_timeout 600;
client_max_body_size 100m;
client_body_buffer_size 256k;
client_body_temp_path /var/cache/nginx/client_temp;
gzip on;
gzip_static on;
gzip_min_length 1024;
gzip_comp_level 5;
gzip_buffers 4 32k;
gzip_http_version 1.1;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
gzip_types text/css text/xml application/javascript;
open_file_cache max=10000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 5;
open_file_cache_errors off;
include /etc/nginx/conf.d/*.conf;
}
# 将 keepalive_timeout 设置为 0,高并发网站中,一般不超过 2s。此参数在 F12 调试页面时,在 Network 的 Headers 的 Response Headers 下可以看到 Connection:keep-alive,如果设置为 0,那么为 Connection:close
keepalive_timeout 0;
再次压测
[root@node-a ~]# ab -c 20000 -n 100000 http://1.1.1.1/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 1.1.1.1 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software: nginx/1.16.0
Server Hostname: 1.1.1.1
Server Port: 80
Document Path: /index.html
Document Length: 612 bytes
Concurrency Level: 20000
Time taken for tests: 4.613 seconds
Complete requests: 100000
Failed requests: 16
(Connect: 0, Receive: 0, Length: 16, Exceptions: 0)
Write errors: 0
Non-2xx responses: 16
Total transferred: 84491904 bytes
HTML transferred: 61193040 bytes
Requests per second: 21676.88 [#/sec] (mean)
Time per request: 922.642 [ms] (mean)
Time per request: 0.046 [ms] (mean, across all concurrent requests)
Transfer rate: 17885.95 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 361 704.8 130 3198
Processing: 2 122 72.5 134 730
Waiting: 1 79 50.5 88 403
Total: 3 483 723.6 305 3354
Percentage of the requests served within a certain time (ms)
50% 305
66% 318
75% 339
80% 757
90% 1111
95% 3251
98% 3298
99% 3325
100% 3354 (longest request)
文件层面
系统层面
# 设置同一个文件同一时间点可以打开 N 次,这个操作在重启之后失效
命令:ulimit -n
返回:128
命令:ulimit -n 200000
nginx 层面
# nginx 进程数,按照 CPU 数目指定
worker_processes 8;
# nginx 子进程允许打开的文件次数
worker_rlimit_nofile 102400;
再次压测
[root@node-a ~]# ab -c 20000 -n 100000 http://1.1.1.1/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 1.1.1.1 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software: nginx/1.16.0
Server Hostname: 1.1.1.1
Server Port: 80
Document Path: /index.html
Document Length: 612 bytes
Concurrency Level: 20000
Time taken for tests: 4.560 seconds
Complete requests: 100000
Failed requests: 25
(Connect: 0, Receive: 0, Length: 25, Exceptions: 0)
Write errors: 0
Non-2xx responses: 25
Total transferred: 84487350 bytes
HTML transferred: 61189125 bytes
Requests per second: 21930.98 [#/sec] (mean)
Time per request: 911.952 [ms] (mean)
Time per request: 0.046 [ms] (mean, across all concurrent requests)
Transfer rate: 18094.64 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 285 493.8 127 3196
Processing: 7 112 93.6 128 1750
Waiting: 0 67 71.7 54 1734
Total: 15 397 532.1 249 3595
Percentage of the requests served within a certain time (ms)
50% 249
66% 339
75% 348
80% 612
90% 1183
95% 1312
98% 1492
99% 3343
100% 3595 (longest request)
小结
适合单个URL的测试,可以支持更多方式去测试,比如使用cookie模仿用户提交表单来测试数据库,但ab是单线程的,不适合测性能高的服务器;
ab并发数不能大于请求数
请求数默认不能超过1024个
ab并发默认不能大于20000, 需要修改apache源代码support目录下ab.c文件,找到:#define MAX_CONCURRENCY 20000 将宏定义的值改大,重新编译安装apache。
ab可以直接在Web服务器本地发起测试请求,不包括数据的网络传输时间以及用户PC本地的计算时间;
没修改内核参数并发超过一千会报错,连接被重置,bingyi了以下,apr_socket_recv这个是操作系统内核的一个参数,在高并发的情况下,内核会认为系统受到了SYN flood攻击,会发送cookies(possible SYN flooding on port 80. Sending cookies),这样会减慢影响请求的速度,所以在应用服务武器上设置下这个参数为0禁用系统保护就可以进行大并发测试了;