本文简要介绍Apache ab(ApacheBench),一个性能基准工具。
Apache ab官方网址在这里。
1 Apache ab是什么
Apache ab原本是一款为了对Apache HTTP server进行基准测试而实现的工具。它的目的是让用户快速确认目标Apache HTTP server的性能,例如测试出QPS等性能指标。
因为Apache ab发出的是标准HTTP请求,所以使用ab也可以对Nginx、Tomcat、Jetty等HTTP server进行性能测试。
1.1 安装ab
Mac
Mac默认已经安装了Apache ab。可以在终端输入如下命令验证:
ab -V
如果输出类似如下内容,则证明Apache ab已在Mac上安装:
Windows
在Windows上安装Apache ab的步骤相对复杂一些,因为Apache并未提供针对Windows的安装包。一般我们可以使用第三方提供的Windows环境下的Apache安装包。
首先进入Apache HTTP Server的下载页面,如下:
点击上图红框中的链接,进入Apache针对Windows系统的说明页面,如下:
一般选择Apache Lounge,进入如下页面:
然后选择对应的Windows版本下载即可。下载完成后解压ZIP包,可以在bin目录下找到ab.exe。这个就是在Windows环境下可执行的ab工具。
1.2 快速体验
Apache ab命令很简单,例如我们使用2个并发一共访问example.org网站10次,命令如下:
ab -n 10 -c 2 https://example.org/
返回结果如下所示:
2 Apache ab参数
Apache ab命令的可用参数说明如下:
参数 | 说明 |
---|---|
-A | 向服务器提供 BASIC 身份验证凭证。用户名和密码用一个": “分隔,并以 base64 编码发送。无论服务器是否需要(即已发送 401 身份验证请求),都会发送该字符串。 |
-b | TCP 发送/接收缓冲区的大小(字节)。 |
-B | 对外连接时绑定的地址。 |
-c | 请求并发数,即一次执行多个请求的数量。默认为一次一个请求。 |
-C | 在请求中添加 Cookie: 一行。参数通常以 name=value 对的形式出现。该字段可重复使用。 |
-d | 不显示 “XX [ms] 表内送达百分比”。 |
-e | 输出一个CSV(逗号分隔值)文件,其中包含每个百分比(从 1%到 100%)的请求处理时间(以毫秒为单位)。 |
-E | 连接到SSL网站时,使用提供的PEM格式客户证书与服务器进行身份验证。该文件应包含客户端证书、中间证书和私钥。(适用于Apache HTTP server 2.4.36及更高版本) |
-f | 指定SSL/TLS协议(SSL2、SSL3、TLS1、TLS1.1、TLS1.2 或 ALL)。(2.4.4及更高版本支持TLS1.1和TLS1.2) |
-g | 将测试结果输出成"gnuplot"或TSV(Tab单独值)文件。该类型文件可使用Gnuplot、IDL、Mathematica、Igor甚至Excel等软件打开。标签位于文件的第一行。 |
-h | 显示使用信息。 |
-H | 向HTTP请求附加额外的Header信息。参数的形式通常是有效的标头行,包含以冒号分隔的field-value对(例如,“Accept-Encoding: zip/zop;8bit”)。 |
-i | 用HEAD请求代替GET请求。 |
-k | 启用HTTP KeepAlive功能,即在一个HTTP会话中执行多个请求。默认不启用。 |
-l | 如果HTTP response的长度不固定,也不会报错。这个参数在动态页面中很有用。适用于Apache HTTP server 2.4.7及更高版本。 |
-m | 自定义HTTP请求的方法。适用于Apache HTTP server 2.4.10及更高版本。 |
-n | 指定压测期间的请求次数总数。默认只执行一次请求。 |
-p | 指定POST请求所要包含的数据文件。需要与-T参数配合使用。 |
-P | 向代理提供BASIC验证凭据。用户名和密码以单个”: “分隔,并以base64编码发送。无论代理是否需要(即已发送407代理验证需求),都会发送该字符串。 |
-q | 默认情况下,ab设定的请求次数(-n)超过150个时,会每隔10%或大约100个请求后输出进度计数。使用-q可以取消这些信息。 |
-r | 当Socket收到错误时不退出。 |
-s | 设置Socket的超时时间,单位是秒。默认为30秒。适用于Apache HTTP server 2.4.4及更高版本。 |
-S | 不显示中位数和标准偏差值,当平均值和中位数相差超过标准偏差的一或两倍时,也不显示警告/错误信息。默认为最小值/最大值/最大值。 |
-t | 用于设定ab基准测试的时长。使用它可以在固定的总时间内对服务器进行基准测试。默认情况下没有时间限制。 |
-T | 用于设定POST/PUT请求的Content-type信息,例如:application/x-www-form-urlencoded。默认为 text/plain。 |
-u | 指定PUT请求所要包含的数据文件。需要与-T参数配合使用。 |
-v | 设置verbosity级别 - 4及以上级别打印标题信息,3及以上级别打印响应代码(404、200 等),2及以上级别打印警告和信息。 |
-V | 显示Apache ab的版本信息。 |
-w | 以HTML table形式打印结果。默认表格为两列宽,白色背景。 |
-x | 用作<table>属性的字符串。属性插入<table here>。 |
-X | 使用代理服务器处理请求。 |
-y | 用作<tr>属性的字符串。 |
-z | 用作<td>属性的字符串。 |
-Z | 指定SSL/TLS密码套件。(具体请查阅openssl相关内容) |
3 Apache ab结果说明
Apache ab的返回结果,说明如下:
参数 | 说明 |
---|---|
Server Software | 第一个成功的response头中返回的值(如果有)。这包括头中从开始到检测到十进制值为32的字符(最明显的是空格或 CR/LF)为止的所有字符。 |
Server Hostname | 命令行中给出的DNS或IP地址。 |
Server Port | Apache ab连接的端口。如果命令行中没有指定端口,则http默认端口为80,https默认端口为443。 |
SSL/TLS Protocol | 客户端和服务器之间协商的协议参数。只有使用SSL时才会打印。 |
Document Path | 从命令行字符串中解析出的请求URI。 |
Document Length | 这是第一个成功返回的文档的大小(以字节为单位)。如果文档长度在测试过程中发生变化,response将被视为错误。 |
Concurrency Level | 测试期间使用的并发客户端数量。 |
Time taken for tests | Apache ab测试的总体时间,即从创建第一个连接开始到收到最后一个response所用的时间。 |
Complete requests | 收到的成功回复数量。 |
Failed requests | 失败的请求数量。如果该数字大于0,则将打印另一行,显示因连接、读取、内容长度不正确或异常而失败的请求数。 |
Write errors | 写入失败的错误次数。 |
Non-2xx responses | 不是200系列HTTP Code的response数量。如果所有回复都是200,则不打印此信息。 |
Keep-Alive requests | 发出Keep-Alive请求的连接数量。 |
Total body sent | 如果测试中有发送数据,则这是测试期间发送的字节总数。如果测试中未发送数据,则省略此字段。 |
Total transferred | 从服务器接收到的字节总数。这个数字基本上就是通过线路发送的字节数。 |
HTML transferred | 从服务器接收到的文档字节总数。该数字不包括HTTP头信息中的字节数。 |
Requests per second | 这是每秒的请求数,即QPS。该值是请求数除以总耗时的结果。 |
Time per request | 所有HTTP请求花费的平均时间,即RT。第一个值的计算公式为并发量 * 时间 * 1000 / 请求次数,第二个值的计算公式为时间 * 1000 / 请求次数。 |
Transfer rate | 传输速率(kb/s),计算公式为总读取次数/1024 次/所用时间。 |
3.1 重要的性能指标
指标参数 | 说明 |
---|---|
Requests per second | 这是衡量服务器性能最重要的指标。它表示了服务器指定接口的吞吐量。 |
Time per request | 这是衡量指定接口的重要指标。它表示了该接口一次请求的平均耗时。 |
Transfer rate | 这是衡量服务器出口网络的重要指标。它可以用来评估服务器出口带宽是否到达瓶颈。对于response body很大的接口,该指标很有参考价值。 |
Percentage of the requests served within a certain time (ms) | 这是压测过程中请求耗时的分布情况。这个指标对于服务器稳定性有参考价值。如果波动较大、较频繁,则需要关注服务器稳定性。 |
4 常见的场景
4.1 带Cookie的Get请求
Apache ab命令如下:
ab -n 100000 -c 10 -C 'cName=cValue' http://localhost:8888/cookieget
以上使用HTTP GET方法请求http://localhost:8888/cookieget接口100000次,请求并发量是10。每个请求的头部带了一个Cookie,即cName=cValue。该接口的实现样例(使用SpringBoot框架)如下:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@RestController
public class CookieGetController {
@GetMapping("/cookieget")
public String cookieGet(HttpServletRequest request, HttpServletResponse response) {
/**
* 读取Cookies
*/
Cookie cookies[] = request.getCookies();
for (Cookie cookie : cookies) {
/**
* 循环打印Cookie内容
*/
System.out.println(cookie.getName() + "=" + cookie.getValue());
}
return "OK";
}
}
执行结果如下图所示:
4.2 指定数据格式的POST请求
Apache ab命令如下:
ab -n 100000 -c 10 -p './pJson.txt' -T 'application/json;charset=utf-8' http://localhost:8888/abPost
以上使用HTTP POST方法请求http://localhost:8888/abPost接口100000次,请求并发量是10。每个请求提交了一个Post数据,即pJson.txt。该文件内容如下:
{
"a": "A"
}
该接口的实现样例(使用SpringBoot框架)如下:
import java.util.Random;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AbPostController {
@PostMapping("/abPost")
public String abPost(@RequestBody AbPostBody abPostBody) throws InterruptedException {
System.out.println("a=" + abPostBody.getA());
Thread.sleep(random.nextLong(100L, 500L));
return "OK";
}
/**
* attribute(s)
*/
private static Random random = new Random();
}
class AbPostBody {
/**
* getters & setters
*/
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
/**
* attribute(s)
*/
private String a;
}
执行结果如下图所示: