|
1 | | -### httptester |
2 | | -A lightweight tool for pressure testing |
| 1 | +近来有需求要对HTTP接口进行压测,于是去了解了一下JMeter,发现虽然功能强大,但本身依赖JAVA,并且依赖图形化界面,不够轻量化,所以想着自己写一个基于命令行的轻量级压测工具,于是就有了httptester。 |
3 | 2 |
|
4 | | -### Get Started |
5 | | -Download the latest binary file [Releases](https://github.com/rocketk/httptester/releases) |
| 3 | +httptester是采用GO语言来编写的,尽管目前仍是早期版本,但是基本功能已经没有问题了。 |
6 | 4 |
|
7 | | -Save the binary file `httptester` into any directory, and open the terminal |
| 5 | +### 快速开始 |
8 | 6 |
|
9 | | -For help |
10 | | -```bash |
11 | | -./httptester run -h |
| 7 | +httptester是一个二进制可执行文件,无需安装。 |
| 8 | + |
| 9 | +下载最新版本:https://github.com/rocketk/httptester/releases |
| 10 | + |
| 11 | +找到自己平台对应的版本下载至本地,将其所在目录放入系统环境变量中。 |
| 12 | + |
| 13 | +#### 常用命令 |
| 14 | + |
| 15 | +获取帮助信息 |
| 16 | + |
| 17 | +```shell |
| 18 | +httptester -h |
| 19 | +httptester run -h |
| 20 | +httptester serve -h |
| 21 | +``` |
| 22 | + |
| 23 | +最简单的压测命令(以压测百度首页为例) |
| 24 | + |
| 25 | +```shell |
| 26 | +httptester run -u 'https://www.baidu.com/' |
12 | 27 | ``` |
13 | 28 |
|
14 | | -#### First Example |
15 | | -```bash |
16 | | -./httptester run -u 'https://www.baidu.com/' |
| 29 | +设定并发量、循环次数、超时时间 |
| 30 | + |
| 31 | +```shell |
| 32 | +httptester run --loop 10 --concurrency 100 --timeout 500ms -u 'https://www.baidu.com/' |
| 33 | +#httptester run --loop 10 --concurrency 100 --timeout 2s -u 'https://www.baidu.com/' |
17 | 34 | ``` |
18 | 35 |
|
19 | | -Output: |
20 | | -```text |
21 | | - 1 / 1 [================================================================================] 100.00% 0s |
| 36 | +#### 结果 |
| 37 | + |
| 38 | +``` |
| 39 | + 100% [==============================] |
22 | 40 | -- Configuration -- |
23 | | -Concurrency: 1 Loop: 1 Timeout: 10000000000 KeepAlive: true TimeUnit: ms Method: GET URL: https://www.baidu.com/ |
| 41 | +Concurrency: 100 Loop: 10 Timeout: 2000 ms KeepAlive: true TimeUnit: ms Method: GET URL: https://www.baidu.com/ |
24 | 42 | Headers: [] |
25 | | -Body: |
| 43 | +Body: |
26 | 44 |
|
27 | 45 | -- Conclusion -- |
28 | | -total count: 1 |
29 | | -success count: 1 |
| 46 | +total count: 1000 |
| 47 | +success count: 981 |
30 | 48 | failed count: 0 |
31 | | -error count: 0 |
32 | | -nature duration: 207 ms |
33 | | -total cost: 207 ms |
34 | | -max: 207 ms |
35 | | -min: 207 ms |
36 | | -median: 207 ms |
37 | | -mean: 207 ms |
38 | | -standard deviation: 0.000000 |
39 | | -throughput: 4 requests/second |
| 49 | +error count: 19 |
| 50 | +nature duration: 2280 ms |
| 51 | +total cost: 195688 ms |
| 52 | +max: 1539 ms |
| 53 | +min: 0 ms |
| 54 | +median: 110 ms |
| 55 | +mean: 195 ms |
| 56 | +standard deviation: 248.309631 |
| 57 | +throughput: 430 requests/second |
| 58 | +``` |
| 59 | + |
| 60 | +| 字段 | 含义 | |
| 61 | +| ------------------ | ------------------------------------------------------------ | |
| 62 | +| total count | 总共的http请求数量,等于loop*concurrency | |
| 63 | +| success count | 总共成功的http请求数量 | |
| 64 | +| failed count | 失败的请求数量,不同于 error count ,只有被【断言】校验不通过的才算失败 | |
| 65 | +| error count | 错误数量,一般是超时或http接口不可用 | |
| 66 | +| nature duration | 自然耗时(区别于下面的总体耗时) | |
| 67 | +| total cost | 总体耗时,每个请求的耗时加总起来的总耗时,在并发情况下会大于自然耗时 | |
| 68 | +| max | 最大单次请求耗时 | |
| 69 | +| min | 最小单次请求耗时 | |
| 70 | +| median | 单次请求耗时中位数 | |
| 71 | +| mean | 平均每次请求耗时 | |
| 72 | +| standard deviation | 每次请求耗时标准差 | |
| 73 | +| throughput | 吞吐量,数值等于 success_count / nature_duration | |
| 74 | + |
| 75 | +### 启动示例服务 |
| 76 | + |
| 77 | +为了更好地测试各种Assertion表达式,你可以通过以下命令启动一个Restful风格的API服务: |
| 78 | + |
| 79 | +```shell |
| 80 | +httptester serve |
| 81 | +#httptester serve -- |
| 82 | +``` |
| 83 | + |
| 84 | +此示例服务是一个典型的Restful风格的API服务,包含以下操作(以curl命令为例): |
| 85 | + |
| 86 | +#### 列出全部用户 |
| 87 | + |
| 88 | +```shell |
| 89 | +curl http://localhost:1234/users |
| 90 | +``` |
| 91 | + |
| 92 | +#### 增加一个新用户 |
| 93 | + |
| 94 | +```shell |
| 95 | +curl -X POST \ |
| 96 | + -d '{"name":"NewUser","age":18,"stature":175,"weight":60,"available":true}' \ |
| 97 | + 'http://localhost:1234/users' |
| 98 | +``` |
| 99 | + |
| 100 | +#### 更新一个已有用户 |
| 101 | + |
| 102 | +```shell |
| 103 | +curl -X PUT \ |
| 104 | + -d '{"name":"NewUser","age":18,"stature":175,"weight":60,"available":true}' \ |
| 105 | + 'http://localhost:1234/users/{id}' |
| 106 | +``` |
| 107 | + |
| 108 | +注意将`{id}`改为实际的用户id |
| 109 | + |
| 110 | +#### 删除一个已有用户 |
| 111 | + |
| 112 | + ```shell |
| 113 | +curl -X DELETE 'http://localhost:1234/users/{id} |
| 114 | + ``` |
| 115 | +
|
| 116 | +### Assertion |
| 117 | +
|
| 118 | +在默认情况下,httptester并不会做断言检测,也就是说只要http请求得到了响应,不论其返回的响应是什么,不论响应码是什么,都会按照成功来计算。但很多情况下,你需要判断其结果是否正确。 |
| 119 | +
|
| 120 | +当前版本的httptester支持3种断言,即 **响应码断言** / **JSON断言** / **正则表达式断言**。 |
| 121 | +
|
| 122 | +以上一节Restful-API服务接口中的“列出所有用户”为例,`curl`格式如下: |
| 123 | +
|
| 124 | +```shell |
| 125 | +curl -i http://localhost:1234/users |
40 | 126 | ``` |
41 | 127 |
|
42 | | -#### More Examples |
43 | | -```bash |
44 | | -./httptester run -u 'https://www.baidu.com/' -c 10 -l 10 |
| 128 | +返回结果: |
| 129 | +
|
| 130 | +```http |
| 131 | +HTTP/1.1 200 OK |
| 132 | +Content-Type: application/json; charset=utf-8 |
| 133 | +Date: Fri, 12 Mar 2021 05:59:12 GMT |
| 134 | +Content-Length: 459 |
| 135 | +
|
| 136 | +[{ |
| 137 | + "id": "30160f4c-a4ee-420b-ba61-fb0f78a3e312", |
| 138 | + "name": "Mary", |
| 139 | + "title": "", |
| 140 | + "price": 0, |
| 141 | + "weight": 60.5, |
| 142 | + "available": true |
| 143 | +}, { |
| 144 | + "id": "04c7aca2-c27b-4ff1-8756-1bdf57ab7993", |
| 145 | + "name": "Benjamin", |
| 146 | + "title": "", |
| 147 | + "price": 0, |
| 148 | + "weight": 65, |
| 149 | + "available": true |
| 150 | +}, { |
| 151 | + "id": "51784d48-4abd-4f01-83df-4cd43869027c", |
| 152 | + "name": "Lee", |
| 153 | + "title": "", |
| 154 | + "price": 0, |
| 155 | + "weight": 50.8, |
| 156 | + "available": false |
| 157 | +}] |
| 158 | +``` |
| 159 | +
|
| 160 | +接下来我们来看在`httptester`中如何来写断言。 |
| 161 | +
|
| 162 | +#### 响应码断言 |
| 163 | +
|
| 164 | +使用`--assert-status-codes`来设定响应码断言,下面的例子表示,只有当http响应码为`200`或`201`时才算请求成功 |
| 165 | +
|
| 166 | +```shell |
| 167 | +httptester run -u 'http://localhost:1234/users' \ |
| 168 | + -c 100 -l 100 \ |
| 169 | + --assert-status-codes '200 201' |
| 170 | +``` |
| 171 | +
|
| 172 | +#### JSON断言 |
| 173 | +
|
| 174 | +此次我们使用“新增一个用户”为例,它的返回值如下: |
| 175 | +
|
| 176 | +```http |
| 177 | +HTTP/1.1 200 OK |
| 178 | +Content-Type: application/json; charset=utf-8 |
| 179 | +Date: Fri, 12 Mar 2021 07:01:50 GMT |
| 180 | +Content-Length: 116 |
| 181 | +
|
| 182 | +{"id":"ddb6b9fe-f0af-40ef-8b44-90e5b150b3ac","name":"NewUser","age":18,"stature":175,"weight":60.5,"available":true} |
| 183 | +``` |
| 184 | +
|
| 185 | +假设我们认为返回值中的`name`值要等于`NewUser`,那么我可以使用`--assert-json-expression`来达到这一目的。注意双等号两侧的空格是必须的。 |
| 186 | +
|
| 187 | +```shell |
| 188 | +httptester run --method POST -u 'http://localhost:1234/users' \ |
| 189 | + -b '{"name":"NewUser","age":18,"stature":175,"weight":60,"available":true}' \ |
| 190 | + -c 100 -l 100 \ |
| 191 | + --assert-json-expression '$.name == NewUser' |
| 192 | +``` |
| 193 | +
|
| 194 | +### 更为复杂的例子 |
| 195 | +
|
| 196 | +添加`header` 设定`method` 添加`body` 添加`timeout` |
| 197 | +
|
| 198 | +```shell |
| 199 | +httptester run --method 'POST' -u 'http://localhost:1234/users' \ |
| 200 | + -H 'Content-Type:application/json' \ |
| 201 | + -H 'accept:application/json' \ |
| 202 | + -b '{"name":"NewUser","age":18,"stature":175,"weight":60,"available":true}' \ |
| 203 | + --timeout 2s \ |
| 204 | + --loop 100 \ |
| 205 | + --concurrency 100 \ |
| 206 | + --assert-status-codes '200 201' \ |
| 207 | + --assert-json-expression '$.name == NewUser' |
| 208 | + -e |
45 | 209 | ``` |
46 | | -This example will start 10 goroutines to send the http request, and each goroutine will repeat sending the same request for 10 times. |
47 | 210 |
|
| 211 | +`-e`表示如果出现失败或报错,将错误信息打印出来 |
48 | 212 |
|
0 commit comments