背景:

项目需要对一批接口进行压测,要求是接口的QPS(Quest Per Second每秒请求数)达到6万以上
由于楼主一直使用的压力测试工具是jmeter,但是jmeter单台电脑无法达到6万的QPS,于是使用网传比较好用的其他性能工具进行压测比较,选出一款符合要求的工具进行压测。

压测机器:Linux 4核8G
由于不同的性能工具压测时消耗的系统资源不一样,防止系统资源造成的干扰,测试时服务器只运行压测工具,且非本机压本机。

示例接口,post请求,请求body可为空
POST https://api.midukanshu.com/logstash/userbehavior/report
返回:
{"code":0,"message":"成功","currentTime":1543386393,"data":[]}

一、 Wrk

wrk是一款现代化的HTTP性能测试工具,即使运行在单核CPU上也能产生显著的压力。最大的优点是它支持多线程,这样更容易发挥多核 CPU 的能力,从而更容易测试出系统的极限能力。

安装

git clone https://github.com/wg/wrk.git
cd wrk/
make

查看版本

./wrk -v

 

参数说明

-c:总的连接数(每个线程处理的连接数=总连接数/线程数)
-d:测试的持续时间,如2s(2second),2m(2minute),2h(hour),默认为s
-t:需要执行的线程总数,默认为2,一般线程数不宜过多. 核数的2到4倍足够了. 多了反而因为线程切换过多造成效率降低
-s:执行Lua脚本,这里写lua脚本的路径和名称,后面会给出案例
-H:需要添加的头信息,注意header的语法,举例,-H “token: abcdef”
—timeout:超时的时间
—latency:显示延迟统计信息

返回结果

Latency:响应时间
Req/Sec:每个线程每秒钟的执行的连接数
Avg:平均
Max:最大
Stdev:标准差
+/- Stdev: 正负一个标准差占比
Requests/sec:每秒请求数(也就是QPS),等于总请求数/测试总耗时
Latency Distribution,如果命名中添加了—latency就会出现相关信息

运行

./wrk -t 5 -c 300 -d 60 --latency https://api.midukanshu.com/logstash/userbehavior/create

 

300个连接数跑60秒:Request/sec(每秒请求数):3322.48

./wrk -t 5 -c 500 -d 60 --latency https://api.midukanshu.com/logstash/userbehavior/create

 

500个连接数跑60秒:Request/sec(每秒请求数):3321.67

可见连接数从300加到500,QPS没有明显变化,就没有再往上加的必要了,再加也只会花更多的时间去坐线程的切换,QPS不一定上升,而且300个连接数时CPU已经跑满,后面会有截图说明

如果post请求的body不为空则指定lua文件进行读取,示例如下:
./wrk -t 5 -c 300 -d 60 --script=post.lua --latency https://api.midukanshu.com/logstash/userbehavior/create
post.lua文件内容
wrk.method = "POST"
wrk.body = ""
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

二、 Apache Benchmark

Apache Benchmark简称 ab,是apache自带的压力测试工具

安装:

sudo yum install httpd-tools

查看版本:

ab -V

 

参数说明

-n 表示请求总数(与-t参数可任选其一)
-c 表示并发数
-t 标识请求时间
-p:模拟post请求,文件格式为gid=2&status=1,配合-T使用
-T:post数据所使用的Content-Type头信息,如-T 'application/x-www-form-urlencoded'

返回结果

Server Software:        nginx/1.13.6   #测试服务器的名字
Server Hostname: api.midukanshu.com #请求的URL主机名
Server Port: 443 #web服务器监听的端口 Document Path: /logstash/userbehavior/create   #请求的URL中的根绝对路径
Document Length: 0 bytes #HTTP响应数据的正文长度 Concurrency Level: 300        # 并发用户数,这是我们设置的参数之一
Time taken for tests: 22.895 seconds #所有这些请求被处理完成所花费的总时间
Complete requests: 50000        # 总请求数量,这是我们设置的参数之一
Failed requests: 99         # 表示失败的请求数量,这里的失败是指请求在连接服务器、发送数据等环节发生异常,以及无响应后超时的情况
Write errors: 0
Total transferred: 96200 bytes    #所有请求的响应数据长度总和。包括每个HTTP响应数据的头信息和正文数据的长度
HTML transferred: 79900 bytes    # 所有请求的响应数据中正文数据的总和,也就是减去了Total transferred中HTTP响应数据中的头信息的长度
Requests per second: 2183.91 [#/sec] (mean) #吞吐率,计算公式:Complete requests/Time taken for tests 总请求数/处理完成这些请求数所花费的时间
Time per request: 137.368 [ms] (mean) # 用户平均请求等待时间,计算公式:Time token for tests/(Complete requests/Concurrency Level)。处理完成所有请求数所花费的时间/(总请求数/并发用户数)
Time per request: 0.458 [ms] (mean, across all concurrent requests) #服务器平均请求等待时间,计算公式:Time taken for tests/Complete requests,正好是吞吐率的倒数。也可以这么统计:Time per request/Concurrency Level
Transfer rate: 652.50 [Kbytes/sec] received #表示这些请求在单位时间内从服务器获取的数据长度,计算公式:Total trnasferred/ Time taken for tests,这个统计很好的说明服务器的处理能力达到极限时,其出口宽带的需求量。

运行

ab -c 300 -t 60 https://api.midukanshu.com/logstash/userbehavior/create

 

300线程跑60秒:Requests per second=2301.68

ab -c 500 -t 60 https://api.midukanshu.com/logstash/userbehavior/create

 

500线程跑60秒:Requests per second=2279.27

可见线程数加到500,还不如300的了,所以有时候线程数不是加的越高越好,更根据服务器的配置,CPU,IO,带宽等的消耗设置合理的线程数
细心的读者可能看出,我虽然设置了-t参数为60s,但实际只运行了20多秒,因为ab跑满50000个request就自己停了,想跑够60s可以使用-n参数

如果post请求的body不为空则指定文件进行读取,示例如下:
ab -n 100 -c 10 -p 'post.txt' -T 'application/x-www-form-urlencoded' 'http://test.api.com/ttk/auth/info/'
post.txt文件内容
devices=4&status=1

三、 Locust

Locust是一个Python编写的分布式的性能测试工具

安装

安装python pip
sudo yum -y install python-pip
通过Python自带的pip安装locust
pip install locustio

查看版本:

locust –version

 

参数说明

--host指定被测试的主机,采用以格式:http://192.168.21.25
-f指定运行 Locust 性能测试文件,默认为: locustfile.py
–-no-web no-web 模式运行测试,需要 -c 和 -r 配合使用
-c指定并发用户数,作用于 –no-web 模式。
-r指定每秒启动的用户数,作用于 –no-web 模式。
-t设置运行时间, 例如: (300s, 20m, 3h, 1h30m). 作用于 –no-web 模式。

返回结果

Name:请求方式,请求路径;
reqs:当前请求的数量;
fails:当前请求失败的数量;
Avg:所有请求的平均响应时间,毫秒;
Min:请求的最小的服务器响应时间,毫秒;
Max:请求的最大服务器响应时间,毫秒;
Median:中间值,单位毫秒;
req/s:每秒钟请求的个数。
Total:各接口的汇总信息

运行:
Locust_demo.py文件内容

# coding=utf-8
from locust import HttpLocust, TaskSet, task
class UserBehavior(TaskSet): @task(1)
def profile(self):
self.client.post("/logstash/userbehavior/report", {}) class WebsiteUser(HttpLocust):
task_set = UserBehavior
min_wait = 0
max_wait = 0

locust -f locust_demo.py --host=https://api.midukanshu.com --no-web -c 300 -t 60s

 

300线程跑60秒:Req/s=730.10

locust -f locust_demo.py --host=https://api.midukanshu.com --no-web -c 500 -t 60s

 

500线程跑60秒:Req/s=741.50

四、 Jmeter

Apache JMeter是Apache组织开发的基于Java的压力测试工具

安装

安装jdk:yum -y list java
yum install -y java-1.8.0-openjdk-devel.x86_64
配置Java环境变量后执行java -version

 

下载:apache-jmeter-3.2.tgz
然后解压到当前传的目录
tar zxvf apache-jmeter-3.2.tgz jmeter

查看版本:

见jmeter主目录

参数说明:

-n : 非GUI 模式执行JMeter
-t : 执行测试文件所在的位置及文件名
-r : 远程将所有agent启动,用在分布式测试场景下,不是分布式测试只是单点就不需要-r
-l : 指定生成测试结果的保存文件, jtl 文件格式
-e : 测试结束后,生成测试报告
-o : 指定测试报告的存放位置

返回结果:

Avg:所有请求的平均响应时间,毫秒;
Min:请求的最小的服务器响应时间,毫秒;
Max:请求的最大服务器响应时间,毫秒;
Err:请求错误个数,错误百分率;
Active:激活的线程数,当Active=0,则说明运行中的线程数为0,则压测结束。
Started:启动的线程数
Finished:完成的线程数

运行脚本:

./jmeter.sh -n -t ./jmx/userbehavior_report.jmx
300个线程跑60秒:

 

Summary + 398526 in 00:00:18 =21959.8/s
Summary = 1018846 in 00:01:04 =15904.6/s
Summary =表示总共运行1分04秒,请求了1018846个接口,这1分04秒内的QPS=15904.6/s
Summary +表示统计最近18秒,请求了398526个接口,即00:00:46到00:01:04期间的18秒,QPS=21959.8/s
500个线程跑60秒:
到这差不多了,500线程跑出来也没300的QPS高,就不放图了

总结:
300线程跑60秒, 对比各压测工具的 QPS:
Wrk=3322.48/s
Ab=2301.68/s
Locust= 730.10/s
Jmeter=21959.8/s
我曾以为的压测结果是:wrk > ab > locust > jmeter
实际结果是:jmeter > wrk > ab > locust

五、资源消耗对比

Top参数解释:

cpu状态
6.7% us — 用户空间占用CPU的百分比。
0.4% sy — 内核空间占用CPU的百分比。
0.0% ni — 改变过优先级的进程占用CPU的百分比
92.9% id — 空闲CPU百分比
0.0% wa — IO等待占用CPU的百分比
0.0% hi — 硬中断(Hardware IRQ)占用CPU的百分比
0.0% si — 软中断(Software Interrupts)占用CPU的百分比
内存状态
8306544k total — 物理内存总量(8GB)
7775876k used — 使用中的内存总量(7.7GB)
530668k free — 空闲内存总量(530M)
79236k buffers — 缓存的内存量 (79M)
各进程(任务)的状态监控
PID — 进程id
USER — 进程所有者
PR — 进程优先级
NI — nice值。负值表示高优先级,正值表示低优先级
VIRT — 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
RES — 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
SHR — 共享内存大小,单位kb
S — 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程
%CPU — 上次更新到现在的CPU时间占用百分比
%MEM — 进程使用的物理内存百分比
TIME+ — 进程使用的CPU时间总计,单位1/100秒
COMMAND — 进程名称(命令名/命令行)

在top基本视图中,按键盘数字“1”,可监控每个逻辑CPU的状况:
可看出压测服务器有4个逻辑CPU

 

300线程跑60秒CPU消耗如图:
Wrk=377.1%
Ab=99.7%
Locust= 100%
Jmeter=396.4%
如果服务器是多核CPU可能在下方看到有些进程CPU占用超过100%,这种一般是该进程使用了多核。
可以看出wrk和jmeter都超过100%,且jmeter的396/4=99%,即使用了服务器99%的性能,
在压力测试过程中,最好时刻留意哪些资源成为了瓶颈,比如:CPU 是不是跑满了,IO 是不是跑满了
查看0.0 wa这里,IO等待所占用的CPU时间的百分比,高过30%时IO压力高。

比较结果:

工具 wrk ab locust jmeter
安装 简单 简单 依赖python 依赖jdk
场景压测 不支持 不支持 支持 支持
UI界面
脚本录制 利用本地ProxyServer或badboy
资源监控 通过JMeterPlugins插件和ServerAgent实现
报告分析 生成HTML报告

虽然jmeter提供UI界面,但是其压测脚本也依赖UI界面,导致其无法在Linux服务器上直接编辑写脚本,只有编写好脚本后再传到Linux服务器。
关于对于压测工具的选择

如果你想做场景的压测,而不是单个接口的压测
可使用jmeter或locust,支持接口串联,接口body参数化,思考时间等复杂场景
如果你压测要求的并发比较高,需要使用分布式压测
可使用jmeter或locust
如果你关注接口的返回,多维度压测报告统计
jmeter,jmeter,jmeter
如果想尽快编写接口,只关注接口的发送,造成的QPS和错误率
可使用wrk或ab
实践中也可以选择自己熟悉的压测工具

由于单台4核8G服务器对待测接口最高能造成2万的QPS,还是距离我需要的6万还有一定距离,这时候可以使用Jmeter的分布式压测

当然还有更多我还没了解到的优秀压测工具,压测结果存在一定局限,仅供参考
欢迎交流指正,感谢阅读。

wrk,ab,locust,Jmeter 压测结果比较的更多相关文章

  1. 【Java分享客栈】未来迈向高级工程师绕不过的技能:JMeter压测

    前言 因为工作需要,久违的从自己的有道云笔记中去寻找压测相关的内容,翻开之后发现还不错,温故一遍后顺便整理出来分享给大家. 题外话,工作8年多,有道云笔记不知不觉都6G多了,扫一眼下来尽是云烟过往,竟 ...

  2. jmeter压测app

    使用代理的方式,录制app端脚本,之后用jmeter压测就没啥好说的了 1.电脑端谷歌设置本地代理(端口号为8888) 2.jmeter设置HTTP代理服务器(端口号为8888) 3.手机端wifi设 ...

  3. Mac 使用ab命令进行压测

    Mac 使用ab命令进行压测 1.在Mac中配置Apache Mac中应该有自带了Apache,详细配置见http://www.cnblogs.com/snandy/archive/2012/11/1 ...

  4. JMeter压测基础(三)——Mysql数据库

    JMeter压测基础(三)——Mysql数据库 环境准备 mysql驱动 JMeter jdbc配置 JMeter jdbc请求 1.下载mysql驱动:mysql-connector-java.ja ...

  5. jmeter压测参数设定(转)

    jmeter压测参数设定 一.基本公式 线程数 = QPS * time: 注:QPS--每秒完成请求的个数:time--每个请求响应完成平均需要时间: 故QPS * time就是所有请求完成响应所需 ...

  6. jmeter压测、操作数据库、分布式linux下运行、webservice接口测试、charles抓包

    一.jmeter压测 在线程组中设置好,然后添加http请求,t添加聚合报告查看压力测试结果,如图: 一般压测时间10-15分钟,如果是稳定性测试,一般n*12小时,这些并发用户一直在请求. tps: ...

  7. jmeter压测之添加负载机

    jmeter压测基本介绍一般基准测试(基准测试时间一般为5分钟)后压测的时间是10-15分钟: 实施测试之前要拿到测试指标 例如:tps要达到多少响应时间要达到多少并发数要达到多少TPS :服务端每秒 ...

  8. jmeter 压测duobbo接口,施压客户端自己把自己压死了

    jmeter 压测duobbo接口,jmeter代码不合理,导致每执行一次请求,会调用一次消耗内存的实例化.导致越压越慢,请求发不出去.这个时候需要考虑修改代码了. 截图中,tps越来越少. 原来初始 ...

  9. jmeter压测-负载配置

    jmeter 压测 一般压测的时间是10-15分钟 TPS:服务端每秒钟处理的请求数  越大越好 响应时间 :越短越好 并发用户数  也就是多少并发 指标给你:tps要达到多少 响应时间要达到多少 并 ...

随机推荐

  1. Java后台解决跨域问题

    首先说一下什么是跨域? JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.那什么是跨域呢,简单地理解就是因为JavaScript同源策略的限制,a.com域名下的js无法操作b.c ...

  2. 建立apk定时自动打包系统第三篇——代码自动更新、APP自动打包系统

    我们的思路是每天下班后团队各成员在指定的时间(例如下午18:30)之前把各自的代码上传到SVN,然后服务器在指定的时间(例如下午18:30)更新代码.执行ant 打包命令.最后将apk包存放在指定目录 ...

  3. 敏捷之旅--携程Scrum Master 新官上任三把火?

      随着敏捷在国内的推行,越来越多的公司和组织开始使用敏捷领导团队. 敏捷团队如雨后春笋之势涌现. 敏捷教练的团队也越来越壮大.   原先只需要一个敏捷教练就能搞定,但是随着团队越来越多,我们难免会将 ...

  4. Linux--shell数组和字符串--09

    一.数组 数组就是一段连续的变量,一段连续的内存存储空间,为了解决变量过多的问题,在同一类变量中,我们不需要去定义多个名字,而是以数组的方式来定义 1.定义数组 declare -a 定义数组 dec ...

  5. Java网络编程 -- NIO非阻塞网络编程

    从Java1.4开始,为了替代Java IO和网络相关的API,提高程序的运行速度,Java提供了新的IO操作非阻塞的API即Java NIO.NIO中有三大核心组件:Buffer(缓冲区),Chan ...

  6. SpringIoC和SpringMVC的快速入门

    更多内容,欢迎关注微信公众号:全菜工程师小辉~ Spring的优势? 降低了组件之间的耦合性 ,实现了软件各层之间的解耦 可以使用容易提供的众多服务,如事务管理,消息服务等 容器提供单例模式支持 容器 ...

  7. 怎样使用U盘安装Windows系统

    准备工作 一个8G及以上的U盘: 软碟通UltraISO,下载地址,非免费,但试用就够了: 系统镜像,推荐去MSDN下载: 安装过程 利用U盘制作启动盘,准备好上述的东西,然后开始制作启动盘: 注意: ...

  8. 表单模糊查询的三种简单方式(springboot-h2-mybatis)

    前几天运营提到说后台管理系统有几个地方想要模糊查询..   想了下是简单的,就是要注意以前方法的被调用情况,进行增量改动,以免牵一发而动全身.整理一波记录下(本次案例是按名字模糊查询学生信息). 三种 ...

  9. CF-920C-Swap Adjacent Elements 贪心

    题意 给你一个1-n的排列. 并给你一个字符串——其中用0和1表示对应数列中的位置上的值可不可以和后面相邻的数交换. 判断该数列能否在限制中交换为不降序数列. 思路 由于刚学了树状数组,一开始以为是用 ...

  10. codeforces 799 C. Fountains(二分+思维)

    题目链接:http://codeforces.com/contest/799/problem/C 题意:要求造2座fountains,可以用钻石,也可以用硬币来造,但是能用的钻石有限,硬币也有限,问能 ...