0%

性能测试工具

10大主流压力/负载/性能测试工具:LoadRunner、Apache JMeter、NeoLoad、WebLOAD、Loadster、Load impact、CloudTest、Loadstorm、阿里云PTS、压测宝。

ApacheBench

一、ApacheBench

  1. ab命令是apache模拟多线程并发请求以测试web服务器负载压力,如httpd、nginx、lighthttp、IIS等。考虑到宽带网络延迟等问题,一般建议在内网使用一台专门压测的机器对其他机器进行测试,提高数据的准确性。
    • 需要注意的是ab进行的一切测试都是基于HTTP
    • 安装apacheyum install httpd
  2. 语法ab [options] [http[s]://]hostname[:port]/path
  3. 参数说明
参数 说明
-n requests Number of requests to perform
-c concurrency Number of multiple requests to make at a time
-t timelimit Seconds to max. to spend on benchmarking.This implies -n 50000
-s timeout Seconds to max. wait for each response.Default is 30 seconds
-b windowsize Size of TCP send/receive buffer, in bytes
-B address Address to bind to when making outgoing connections
-p postfile File containing data to POST. Remember also to set -T
-u putfile File containing data to PUT. Remember also to set -T
-T content-type Content-type header to use for POST/PUT data, eg.’application/x-www-form-urlencoded’ Default is ‘text/plain’
-v verbosity How much troubleshooting info to print
-w Print out results in HTML tables
-i Use HEAD instead of GET
-x attributes String to insert as table attributes
-y attributes String to insert as tr attributes
-z attributes String to insert as td or th attributes
-C attribute Add cookie, eg. ‘Apache=1234’. (repeatable)
-H attribute Add Arbitrary header line, eg. ‘Accept-Encoding: gzip’.Inserted after all normal header lines. (repeatable)
-A attribute Add Basic WWW Authentication, the attributes are a colon separated username and password.
-P attribute Add Basic Proxy Authentication, the attributes are a colon separated username and password.
-X proxy:port Proxyserver and port number to use
-V Print version number and exit
-k Use HTTP KeepAlive feature
-d Do not show percentiles served table.
-S Do not show confidence estimators and warnings.
-q Do not show progress when doing more than 150 requests
-g filename Output collected data to gnuplot format file.
-e filename Output CSV file with percentages served
-r Don’t exit on socket receive errors.
-h Display usage information (this message)
-Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)
-f protocol Specify SSL/TLS protocol (SSL3, TLS1, TLS1.1, TLS1.2 or ALL)
  1. 使用 ab -n 100 -c 50 http://127.0.0.1/index.php

Webbench

  1. 安装Webbench

    1
    2
    3
    4
    5
    6
    7
    8
    yum install ctags
    yum install gcc
    mkdir -m 644 -p /usr/local/man/man1

    wget http://home.tiscali.cz/~cz210552/distfiles/webbench-1.5.tar.gz
    tar zxvf webbench-1.5.tar.gz
    cd webbench-1.5
    make && make install
  2. 语法 webbench [options] URL

  3. 参数说明

参数 说明
-f –force
-r –reload
-t –time
-p –proxy server:port
-c –clients
-9 –http09
-1 –http10
-2 –http11
–get Use GET request method.
–head Use HEAD request method.
–options Use OPTIONS request method.
–trace Use TRACE request method.
-? -h
-V –version
  1. 使用webbench -c 100 -t 10 http://www.qq.com/index.php

http_load

  1. 安装http_load

    1
    2
    3
    4
    5
    6
    7
    yum -y install gcc gcc-c++

    wget http://acme.com/software/http_load/http_load-12mar2006.tar.gz
    tar xzvf http_load-12mar2006.tar.gz
    cd http_load-12mar2006
    mkdir /usr/local/man
    make && make install
  2. 语法

    1
    2
    3
    4
    5
    6
    ./http_load [-checksum] [-throttle] [-proxy host:port] [-verbose] [-timeout secs] [-sip sip_file]
    -parallel N | -rate N [-jitter]
    -fetches N | -seconds N
    url_file
    One start specifier, either -parallel or -rate, is required.
    One end specifier, either -fetches or -seconds, is required.
  3. 使用

    • cd http_load-12mar2006
    • vim url,编辑输入要测试的url,保存退出
    • ./http_load -p 100 -s 10 url

Jmeter

  1. Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。它可以用于测试静态和动态资源,例如静态文件、Java小服务程序、CGI脚本、Java对象、数据库、FTP服务器等等。JMeter可以用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能。另外,JMeter能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证你的程序返回了你期望的结果。为了最大限度的灵活性,JMeter允许使用正则表达式创建断言。

  2. 使用

    • 安装

      • 官网
      • 选择编译好的二进制文件Binaries下载
      • 解压sudo tar -zxvf apache-jmeter-5.3.tgz -C /usr/local/
      • 运行一下/usr/local/apache-jmeter-5.3/bin/jmeter,正常会弹出一个jmeter界面出来
      • 加入环境变量,编辑~/.bash_profile,加入jmeter的安装目录,如:
      1
      2
      export JMETER_HOME=/usr/local/apache-jmeter-5.3/bin
      export PATH=$JMETER_HOME:$PATH
      • 刷新让环境变量生效source ~/.bash_rpofile
      • 查看是否成功jmeter -v,正常情况会有如下输出:
      1
      2
      3
      4
      5
      6
      7
           _    ____   _    ____ _   _ _____       _ __  __ _____ _____ _____ ____
      / \ | _ \ / \ / ___| | | | ____| | | \/ | ____|_ _| ____| _ \
      / _ \ | |_) / _ \| | | |_| | _| _ | | |\/| | _| | | | _| | |_) |
      / ___ \| __/ ___ \ |___| _ | |___ | |_| | | | | |___ | | | |___| _ <
      /_/ \_\_| /_/ \_\____|_| |_|_____| \___/|_| |_|_____| |_| |_____|_| \_\ 5.3

      Copyright (c) 1999-2020 The Apache Software Foundation
    • 常见设置

      • 界面设置永久中文
        • cd your_jmeter_path/bin
        • 修改jmeter.properties文件,第三十七行左右,修改language=zh_CN保存
        • 重启
      • 界面临时设置中文:Options->Choose Langue
    • 使用

      • 在终端中运行jmeter
      • 在弹出的UI界面中选择文件->新建测试计划
      • 创建线程组
        • 选中测试计划,右键添加->线程(用户)->线程组
        • 设置线程数(虚拟用户数)和循环次数(每个虚拟用户发送N遍请求),Ramp-Up一般默认
      • 配置元件
        • 选中线程组,右键添加->配置元件->HTTP请求默认值,设置本次测试计划接口地址和端口等信息,当前测试计划共享
        • 选中线程组,右键添加->配置元件->HTTP信息头管理器,设置请求头信息,当前测试计划共享
      • 配置取样器
        • 选中线程组,优先添加->取样器->HTTP请求,可以设置当前接口的请求信息,如果域名一样可以共享HTTP请求默认值信息
      • 配置断言
        • 选中线程组,优先添加->断言->响应断言,可以根据响应的数据来判断请求是否正常
      • 配置结果分析
        • 选中线程组,优先添加->监听器->察看结果树
    • 可以根据自己的需求添加各种选项

      • 配置完后保存test.jmx(等会终端运行要用到)
      • 在终端中运行jmeter -n -t your_path/test.jmx -l your_path/result.txt -e -o your_path/webreport
        • your_path/test.jmx: 为测试计划文件路径
        • your_path/result.txt:为测试结果文件路径
        • your_path/webreport:为测试结果报告保存路径
      1
      2
      3
      4
      5
      6
      7
      8
      ================================================================================
      Don't use GUI mode for load testing !, only for Test creation and Test debugging.
      For load testing, use CLI Mode (was NON GUI):
      jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]
      & increase Java Heap to meet your test requirements:
      Modify current env variable HEAP="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m" in the jmeter batch file
      Check : https://jmeter.apache.org/usermanual/best-practices.html
      ================================================================================

基于ab的压测实验

  1. 安装环境(默认情况下Mac自带ab)
    • 安装brew,传送门
    • 下载httpd源码包,传送门,移动至/usr/local/src
    • 安装httpd依赖
      • brew install pcre apr apr-util
    • 安装httpd服务
      • cd /usr/local/src
      • sudo tar -zxvf httpd-2.4.46.tar.gz
      • cd httpd-2.4.46
      • sudo ./configure –prefix=/usr/local/httpd-2.4.46 –with-apr=/usr/local/Cellar/apr/1.7.0 –with-apr-util=/usr/local/Cellar/apr-util/1.6.1_3
      • sudo make && sudo make install
  2. ab的简单使用
    • 模拟100个用户发起100次请求:ab -n 100 -c 100 http://baidu.com/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking baidu.com (be patient).....done


Server Software: Apache # 模拟请求的web服务器信息
Server Hostname: baidu.com # 模拟请求中的主机部分名称
Server Port: 80 # 模拟请求中的服务器监听端口

Document Path: /index.html
Document Length: 7387 bytes # http响应数据的正文长度。

Concurrency Level: 100 # 并发级别,即并发数,模拟请求中-c参数指定的数量
Time taken for tests: 1.482 seconds # 总共花费的时间
Complete requests: 100 # 总共发起的请求数量,模拟请求中-n参数指定的数量
Failed requests: 12 # 失败的请求数量,通过该数值和Complete requests相除可以计算请求的失败率,作为测试结果的重要参考。
(Connect: 0, Receive: 0, Length: 12, Exceptions: 0)
Total transferred: 676808 bytes # 总共传输的数据量(从被测服务器接收到的总数据量),包括index.html的文本内容和请求头信息,等于
Document Length * (Complete requests - Failed requests)

HTML transferred: 650056 bytes # 从服务器接收到的index.html文件的总大小,等于Document Length * Complete requests
Requests per second: 67.50 [#/sec] (mean) # 平均每秒完成的请求数即QPS,是一个平均值,等于Complete requests/Time taken for tests
Time per request: 1481.567 [ms] (mean) # 用户平均请求等待时间,是从用户角度计算完成一个请求所需要的时间,等于
Time taken for tests / (Complete requests / Concurrency Level),约等于下一项乘以并发数
Time per request: 14.816 [ms] (mean, across all concurrent requests) # 服务器平均请求处理时间,是从服务器角度计算完成一个请求的时间,等于
Time taken for tests / Complete requests,也等于Time per request / Concurrency Level
Transfer rate: 446.11 [Kbytes/sec] received # 网络传输速度(对于大文件的请求测试,这个值很容易成为系统瓶颈所在),等于
Total transferred / Time taken for tests

# 以下数据是针对第一个Time per request进行细分和统计,一个请求的响应时间可以分成三个部分:
网络链接(Connect)
系统处理(Processing)
等待(Waiting)

其中Total并不等于前三行数据相加,因为前三行的数据并不是在同一个请求中采集到的,可能某个请求的网络延迟最短,但是系统处理时间是最长的,所以Total是从整个请求所需要的时间的角度来统计的。

表中:
min表示最小值
mean表示平均值;
[+/-sd]表示标准差(Standard Deviation),也称均方差(mean square error),表示数据的离散程度,数值越大表示数据越分散,系统响应时间越不稳定;
median表示中位数;
max表示最大值。

Connection Times (ms)
min mean[+/-sd] median max
Connect: 17 29 7.9 26 46
Processing: 22 412 323.0 346 1368
Waiting: 0 144 210.3 71 1361
Total: 39 441 323.5 372 1394

# 以下数据是对此次并发请求的一个总结,第一行表示50%的请求都是在372ms内完成的,以此类推。
Percentage of the requests served within a certain time (ms)
50% 372
66% 560
75% 766
80% 783
90% 893
95% 964
98% 1029
99% 1394
100% 1394 (longest request)
  1. node

实验一:创建基于node的http服务

  • server.js,内容见下方
  • 运行此node服务node server.js
  • 模拟请求10000次,并发数依次10、100、1000等增加ab -n 10000 -c 10 http://localhost:3000/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const http = require('http');

let port = process.env.port | 3000

http.createServer(app).listen(port, () => {
console.log(`server is listening ${port}`)
})

let num = 0;
function app(req, res) {
console.log(`第${num++}次访问`)
res.end(getdata().toString())
}

function getdata() {
let size = 1 * 1024
let arr = new Array(size)
for (let i = 0; i < arr.length; i++) {
arr[i] = 1
}
return arr;
}

实验二:基于mongodb查询测试

  • 安装mongose模块npm install mongose
  • server.js,内容见下方
  • 运行此node服务node server.js
  • 模拟请求10000次,并发数依次10、100、1000等增加ab -n 10000 -c 10 http://localhost:3000/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const http = require('http');

let port = process.env.port | 3000

http.createServer(app).listen(port, () => {
console.log(`server is listening ${port}`)
})

let num = 0;
function app(req, res) {
console.log(`第${num++}次访问`)
getDataFromDb(res)
}

function getdata() {
let size = 1 * 1024
let arr = new Array(size)
for (let i = 0; i < arr.length; i++) {
arr[i] = 1
}
return arr;
}

function getDataFromDb(res){
let data = Blog.findOne({},(err,result) => {
res.end(result.toString())
})
}

const mongoose = require("mongoose")
mongoose.connect('mongodb://localhost:27017/study', {useNewUrlParser: true, useUnifiedTopology: true });

const Schema = mongoose.Schema;
const blogSchema = new Schema({
title: String,
body: []
});
const Blog = mongoose.model('Blog', blogSchema);
let obj = {title:"tim",body:getdata()}
const post = new Blog(obj);
post.save()
  1. 遇到的问题

问题1:socket: Too many open files (24)

查看系统用户所有限制值:ulimit -a

设置可打开的文件描述符:ulimit -n 1000

问题2:Mac下设置ulimit过大时会提示ulimit: setrlimit failed: invalid argument

查看系统最大设置数:sysctl kern.maxfilessysctl kern.maxfilesperproc

1
2
3
4
5
6
7
8
9
-t: cpu time (seconds)              unlimited
-f: file size (blocks) unlimited
-d: data seg size (kbytes) unlimited
-s: stack size (kbytes) 8192
-c: core file size (blocks) 0
-v: address space (kbytes) unlimited
-l: locked-in-memory size (kbytes) unlimited
-u: processes 1392
-n: file descriptors 256

问题3:apr_socket_recv: Connection reset by peer (54)

这个报错一般是由于使用的MacOSX默认自带的ab限制了并发数导致的,可以通过下载最新版的httpd源码包重新编译,运行编译好的ab

  1. 一些概念
    • 吞吐率(Requests per second):服务器并发处理能力的量化描述,单位是reqs/s,指的是某个并发用户数下单位时间内处理的请求数。
      • 某个并发用户数下单位时间内能处理的最大请求数,称之为最大吞吐率。
      • 计算公式:总请求数 / 处理完成这些请求数所花费的时间,即Request per second = Complete requests / Time taken for tests
    • 并发连接数(The number of concurrent connections):某个时刻服务器所接受的请求数目,简单的理解就是一个会话。
    • 并发用户数(The number of concurrent users,Concurrency Level):一个用户可能同时会产生多个会话(并发连接数),即并发连接数 >= 并发用户数
    • 用户平均请求等待时间(Time per request)
      • 计算公式:处理完成所有请求数所花费的时间 / (总请求数 / 并发用户数),即 Time per request = Time taken for tests / ( Complete requests / Concurrency Level)
    • 服务器平均请求等待时间(Time per request: across all concurrent requests)
    • 计算公式:处理完成所有请求数所花费的时间 / 总请求数,即Time taken for / testsComplete requests
    • 可以看到,它是吞吐率的倒数。
    • 同时,它也等于用户平均请求等待时间/并发用户数,即 Time per request / Concurrency Level
  1. 参考