文章目录
本文介绍几种简单的并发测试方法。
本文分为五部分,即ab、postman、jmeter、代码模拟、testng。
一、AB
ApacheBench 是 Apache 服务器自带的一个web压力测试工具,简称ab。
ab又是一个命令行工具,对发起负载的本机要求很低,根据ab命令可以创建很多的并发访问线程,模拟多个访问者同时对某一URL地址进行访问,因此可以用来测试目标服务器的负载压力。总的来说ab工具小巧简单,可以提供需要的基本性能指标,但是没有图形化结果,不能监控。
执行命令 ab -n -c url
ab [选项] [http[s]://]主机名[:端口]/路径
# 常用选项
-n requests:执行的请求总数
-c concurrency:并发请求数
-t timelimit:测试持续的最长时间(秒)
-k:启用 HTTP KeepAlive 功能
-H header:添加自定义请求头
-T content-type:POST/PUT 数据的 Content-type
-p postfile:包含 POST 数据的文件
-C cookie:添加 Cookie
-A auth-username:password:基本认证凭据
-X proxy:port:使用代理服务器
1、基本示例
简单测试(100请求,1并发)
ab -n 100 http://www.baidu.com/
# 运行结果
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking www.baidu.com (be patient).....done
Server Software: bfe
Server Hostname: www.baidu.com
Server Port: 80
Document Path: /
Document Length: 2381 bytes
Concurrency Level: 1
Time taken for tests: 6.696 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 249700 bytes
HTML transferred: 238100 bytes
Requests per second: 14.93 [#/sec] (mean)
Time per request: 66.958 [ms] (mean)
Time per request: 66.958 [ms] (mean, across all concurrent requests)
Transfer rate: 36.42 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 26 29 1.4 29 32
Processing: 35 38 1.9 38 44
Waiting: 35 38 1.9 38 44
Total: 61 67 2.9 67 74
Percentage of the requests served within a certain time (ms)
50% 67
66% 68
75% 69
80% 69
90% 71
95% 72
98% 73
99% 74
100% 74 (longest request)
并发测试(10请求,10并发)
ab -n 10 -c 10 http://www.baidu.com/
# 运行结果
[root@server2 ~]# ab -n 10 -c 10 http://www.baidu.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking www.baidu.com (be patient).....done
Server Software: bfe
Server Hostname: www.baidu.com
Server Port: 80
Document Path: /
Document Length: 2381 bytes
Concurrency Level: 10
Time taken for tests: 0.209 seconds
Complete requests: 10
Failed requests: 0
Write errors: 0
Total transferred: 26622 bytes
HTML transferred: 25346 bytes
Requests per second: 47.74 [#/sec] (mean)
Time per request: 209.480 [ms] (mean)
Time per request: 20.948 [ms] (mean, across all concurrent requests)
Transfer rate: 124.11 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 26 28 1.6 28 31
Processing: 35 81 33.9 91 119
Waiting: 34 54 22.7 50 99
Total: 60 109 35.3 118 148
Percentage of the requests served within a certain time (ms)
50% 118
66% 137
75% 138
80% 148
90% 148
95% 148
98% 148
99% 148
100% 148 (longest request)
** 带时间限制的测试(30秒内尽可能多的请求,10并发)**
ab -t 30 -c 10 http://www.baidu.com/
# 运行结果
[root@server2 ~]# ab -t 30 -c 10 http://www.baidu.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking www.baidu.com (be patient)
Finished 2494 requests
Server Software: bfe
Server Hostname: www.baidu.com
Server Port: 80
Document Path: /
Document Length: 2381 bytes
Concurrency Level: 10
Time taken for tests: 30.000 seconds
Complete requests: 2494
Failed requests: 0
Write errors: 0
Total transferred: 6231155 bytes
HTML transferred: 5941619 bytes
Requests per second: 83.13 [#/sec] (mean)
Time per request: 120.290 [ms] (mean)
Time per request: 12.029 [ms] (mean, across all concurrent requests)
Transfer rate: 202.83 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 26 39 11.7 40 120
Processing: 34 70 16.3 70 130
Waiting: 34 46 9.4 40 120
Total: 61 109 17.3 110 190
Percentage of the requests served within a certain time (ms)
50% 110
66% 110
75% 120
80% 120
90% 130
95% 140
98% 150
99% 154
100% 190 (longest request)
启用 KeepAlive
ab -n 1000 -c 10 -k http://www.baidu.com/
# 运行结果
[root@server2 ~]# ab -n 1000 -c 10 -k http://www.baidu.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking www.baidu.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: bfe
Server Hostname: www.baidu.com
Server Port: 80
Document Path: /
Document Length: 2381 bytes
Concurrency Level: 10
Time taken for tests: 12.011 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Keep-Alive requests: 0
Total transferred: 2497628 bytes
HTML transferred: 2381512 bytes
Requests per second: 83.26 [#/sec] (mean)
Time per request: 120.112 [ms] (mean)
Time per request: 12.011 [ms] (mean, across all concurrent requests)
Transfer rate: 203.07 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 26 42 14.2 40 101
Processing: 35 77 18.8 80 139
Waiting: 34 48 11.8 42 128
Total: 61 119 19.5 120 200
Percentage of the requests served within a certain time (ms)
50% 120
66% 130
75% 130
80% 130
90% 140
95% 150
98% 160
99% 170
100% 200 (longest request)
2、高级用法
POST 请求测试
创建包含 POST 数据的文件(如 data.json),然后:
ab -n 100 -c 10 -p data.json -T 'application/json' http://example.com/api
# 运行结果
带自定义请求头
ab -n 100 -H "Authorization: Bearer token123" http://example.com/api
# 运行结果
带 Cookie
ab -n 100 -C "sessionid=123456" http://example.com/dashboard
# 运行结果
对于 HTTPS 测试,ab 会忽略证书验证
二、postman
1、添加 Collection
可以改名称
2、添加要测试的URL
添加请求的测试相关信息,并设置测试通过的判断条件,本示例仅仅以返回状态200为标准。设置完成后要点击保存。
多添加几个请求或只添加一个请求,都可以。添加完成后进行测试。
3、选中添加的Collection,设置运行时参数
4、结果如下
三、JMeter
Meter也是一款性能测试工具,是图形化的。
http://jmeter.apache.org/
功能比较多,详细参考官方网站
四、代码模拟
CountDownLatch是一个计数器闭锁,通过它可以完成类似于阻塞当前线程的功能,即:一个线程或多个线程一直等待,直到其他线程执行的操作完成。
CountDownLatch用一个给定的计数器来初始化,该计数器的操作是原子操作,即同时只能有一个线程去操作该计数器。调用该类await方法的线程会一直处于阻塞状态,直到其他线程调用countDown方法使当前计数器的值变为零,每次调用countDown计数器的值减1。当计数器值减至零时,所有因调用await()方法而处于等待状态的线程就会继续往下执行。这种现象只会出现一次,因为计数器不能被重置。
下图和它的方法可以体现出来:
// CountDownLatch类只提供了一个构造器
//参数count为计数值
public CountDownLatch(int count) { };
//下面这3个方法是CountDownLatch类中最重要的方法(上图能够反映出来)
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException { };
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
//将count值减1
public void countDown() { };
还需要看一个类Semaphore
Semaphore与CountDownLatch相似,不同的地方在于Semaphore的值被获取到后是可以释放的,并不像CountDownLatch那样一直减到底。
它也被更多地用来限制流量,类似阀门的 功能。如果限定某些资源最多有N个线程可以访问,那么超过N个主不允许再有线程来访问,同时当现有线程结束后,就会释放,然后允许新的线程进来。有点类似于锁的lock与 unlock过程。相对来说他也有两个主要的方法:
- 用于获取权限的acquire(),其底层实现与CountDownLatch.countdown()类似;
- 用于释放权限的release(),其底层实现与acquire()是一个互逆的过程。
通过这两个类可以进行并发的模拟:
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
@Slf4j
public class CuncurrencyTest {
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程总数
public static int threadTotal = 200;
public static int count = 0;
public static void main(String[] args) throws InterruptedException {
// 定义线程池
ExecutorService executorService = Executors.newCachedThreadPool();
// 定义信号量 最大的线程数量
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
add();
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count);
}
private static void add() {
count++;
}
}
五、Testng 并发测试
1、注解方式
@Test注解上可通过配置threadPoolSize来实现并发,threadPoolSize和invocationCount是结合使用的,当invocationCount=1的时候,threadPoolSize没有意义。invocationCount表示方法被调用的次数,如果不配置threadPoolSize,该方法会被顺序执行5次,如果配置threaPoolSize=4,下图所示的方法会一次以4个线程并发执行,缩短执行时间。
下面的例子是输出进程ID,threadPoolSize用来指明线程池的大小,也就是并发的线程数目是多少。5次调用,有3个线程可调用。
@Test(invocationCount = 50, threadPoolSize = 3)
public void test() {
System.out.println(1);
System.out.printf("Thrad Id : %s%n", Thread.currentThread().getId());
}
2、配置文件方式
TestNG可以以多线程的模式运行所有的test,这样可以获得最大的运行速度,最大限度的节约执行时间。当然,并发运行也是有代价的,就是需要我们的代码是线程安全的。
并发运行测试的话,需要我们指定运行的配置文件,一个示例如下:
<suite name="My suite" parallel="methods" thread-count="4">
#说明:在当前测试规划的执行过程中,为每个测试方法的执行使用单独的线程,最多并发4个线程。
<suite name="My suite" parallel="tests" thread-count="4">
# 说明:在当前测试规划的执行过程中,为每个测试用例的执行使用单独的线程(该测试用例中的测试方法共享一个线程),最多并发4个线程。
<suite name="My suite" parallel="classes" thread-count="4">
# 说明:在当前测试规划的执行过程中,为每个测试类的执行使用单独的线程(该测试类中的测试方法共享一个线程),最多并发4个线程。
<suite name="My suite" parallel="instances" thread-count="4">
# 说明:在当前测试规划的执行过程中,为每个测试类实例的执行始终使用唯一的线程(该测试实例中的测试方法共享一个线程),最多并发4个线程。
#注意:这里的parallel默认值为"none"。曾经的"true", "false"已经过时了,不建议使用。
#1.Parallel=”methods”的意思是指TestNG会将method作为并发的元子单位,即每个method运行在自己的thread中。如果parallel=”tests”,则指会将test 作为并发的元子单位
#2.Thread-count=”2”是指,运行的时候,并发度为2,同时会有两个线程在运行。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="methods" thread-count="2">
<test verbose="1" preserve-order="true" name="Test1">
<classes>
<!-- 可以多个 -->
<class name="org.eureka.client.userservice.test.Test1" />
</classes>
</test>
</suite>
public class Test1 {
@Test(groups = { "testng-cuncurrency" })
public void aThreadPool() {
System.out.println("#ThreadA: " + Thread.currentThread().getId());
}
@Test(groups = { "testng-cuncurrency" })
public void bThreadPool() {
System.out.println("#ThreadB: " + Thread.currentThread().getId());
}
@Test(groups = { "testng-cuncurrency" })
public void cThreadPool() {
System.out.println("#ThreadC: " + Thread.currentThread().getId());
}
}
测试结果
按照上述配置修改查看结果即可。
以上,极其简单的介绍了并发测试的几种方法,本专栏主要是介绍spring cloud及其相关组件的。