程序员小白如何学会用 ab 压测接口(linux)

一、Apache Bench 介绍

首先老样子,介绍下ab是个什么东西

Apache Bench 是 Apache 服务器自带的一个web压力测试工具,简称 ab。

二、Apache Bench 原理

1.初始化

  • ab工具首先初始化测试环境,包括解析命令行参数、设置目标的请求url、并发数、总请求等。

2.创建连接

  • 根据指定的参数,ab工具会创建多个线程,模拟用户同时访问目标的请求url,同时发起http请求

3.发送请求

  • ab工具通过这些并发连接向目标服务器发送http请求,请求的数量由总请求数决定。
  • 每个请求可以是简单的GET请求,也可以是复杂的POST请求,具体取决与需求。

4.接收响应

  • ab工具接收服务器返回服务器返回的HTTP响应,并且会记录每个响应的状态码、响应时间、传输的数据量等信息

5.统计数据

  • 在所有请求完成后,ab工具会统计并计算各种性能指标,包括每秒请求数、平均响应时间、最长和最短响应时间、成功和失败请求数等。

6.输出结果

  • 最后,ab工具会将结果输出到控制台,可以进一步分析和参考

三、ab命令具体参数

模拟发送get请求

ab -n 100 -c 10 http://localhost:3001/api/v1/hello

模拟发送post请求

ab -n 10000 -c 1000 -p request.json -v 4 -s 36000 -T application/json -H "Authorization: Bearer xxx" http://localhost:3001/api/v1/saveTask -n 10000:总共发送10000个请求。 -c 1000:并发数为1000,同时发送的请求数,也称为并发连接数。 -p request.json:指定包含请求体的文件。 -v 1-4表示不同的输出日志等级,1基本信息,4更详细的信息,包括请求和响应的内容。 -T application/json:指定请求体的Content-Type。 -H "Authorization: Bearer xxx":指定自定义的HTTP头部。 -s 配置单次超时时间,默认30s。(这个建议配置时间长一点,以防万一超时中断测试) -l 忽略内容长度检查(如果每次响应长度不同,ab默认为请求失败) -m 指定http方法,默认情况下使用GET请求

如何发送form-data请求

ab -n 1 -c 1 -p postdata.txt -v 4 -m POST -T 'multipart/form-data; boundary=123454321' http://localhost:3001/api/v1/asr/file/stream

这里遇到坑了,来跟大家讲下

这个postdata.txt格式必须严谨,不然ab请求则会报非200状态码,以为该请求失败

正常格式应该为:

------WebKitFormBoundaryM1tLdAWapR8WCJSe Content-Disposition: form-data; name="file"; filename="01-29.mp3" Content-Type: audio/mpeg <这里应该为对应文件的二进制> ------WebKitFormBoundaryM1tLdAWapR8WCJSe--<这里应该与开头相对应,不管是啥数据只要对应上即可,数字也行,这里的作用呢是起到一个分界符的概念>

按说这么做已经可以了,but这里有坑,就在于换行符,你手动输入是没有换行符这个概念的,所以ab会报非200错误码,比如参数错误等

这时我的解决方法是用到一段pyhon脚本来生成对应上传文件的postdata.txt

python生成postdata.txt

import os # 文件路径 mp3_file_path = 'xxx.mp3' postdata_file_path = 'xxx-postdata.txt' # 边界 boundary = 'WebKitFormBoundaryM1tLdAWapR8WCJSe' # 读取 MP3 文件内容 with open(mp3_file_path, 'rb') as mp3_file:    mp3_content = mp3_file.read() # 生成 multipart/form-data 内容 postdata_content = (    f'--{boundary}\r\n'    f'Content-Disposition: form-data; name="file"; filename="{os.path.basename(mp3_file_path)}"\r\n'    f'Content-Type: audio/mpeg\r\n\r\n' ).encode('utf-8') + mp3_content + f'\r\n--{boundary}--\r\n'.encode('utf-8') # 写入 postdata.txt 文件 with open(postdata_file_path, 'wb') as postdata_file:    postdata_file.write(postdata_content) print(f'{postdata_file_path} 文件已生成。')

这么做参数就好了,当然这个postdata.txt名称可以随意

然后用python实现自动化执行,最后查看输出结果记录分析即可

python实现自动化执行

import subprocess import time import os # 定义测试参数 tests = [         {"total": 100, "concurrent": 1},   {"total": 500, "concurrent": 5},   {"total": 1000, "concurrent": 10},   {"total": 2000, "concurrent": 20},   {"total": 4000, "concurrent": 40},   {"total": 6000, "concurrent": 60},   {"total": 8000, "concurrent": 80},   {"total": 10000, "concurrent": 100},   {"total": 20000, "concurrent": 200},   {"total": 30000, "concurrent": 300},   {"total": 40000, "concurrent": 400},   {"total": 50000, "concurrent": 500},   {"total": 60000, "concurrent": 600},   {"total": 80000, "concurrent": 800},   {"total": 100000, "concurrent": 1000} ] # 目标 URL url = "http://localhost:3001/api/v1/asr/file/stream" # 请求体文件 request_body_file = "xxx-postdata.txt" # HTTP 头部 headers = [    "multipart/form-data; boundary=WebKitFormBoundaryM1tLdAWapR8WCJSe" ] # 生成 ab 命令 def generate_ab_command(total, concurrent):    command = [        "ab",        "-n", str(total),        "-c", str(concurrent),        "-p", request_body_file,        "-v", "4",        "-s", "360000",        "-l",        "-m", "POST",        "-T", headers[0]   ]    command.append(url)    return command # 执行测试并将结果输出到文件 def run_test(total, concurrent, output_file):    command = generate_ab_command(total, concurrent)    with open(output_file, "w") as f:        f.write(f"Running test with total={total} and concurrent={concurrent}\n")        f.write("="*80 + "\n")        subprocess.run(command, stdout=f, stderr=subprocess.STDOUT)        f.write("\n" + "="*80 + "\n\n")    print(f"Test with total={total} and concurrent={concurrent} completed. Output written to {output_file}")    print(f"Sub-command for total={total} and concurrent={concurrent} executed.") # 创建输出目录 output_dir = "ab_test_results" os.makedirs(output_dir, exist_ok=True) # 按顺序执行每组测试 for test in tests:    # 生成输出文件名    output_file_name = f"{test['total']}-{test['concurrent']}-{os.path.basename(request_body_file)}"    output_file = os.path.join(output_dir, output_file_name)        run_test(test["total"], test["concurrent"], output_file)    print("Waiting for 60 seconds before the next test...")    time.sleep(60) print("All tests completed.")

动态处理不同请求,并发请求,得到响应重定向对应文件中,每单次请求执行完毕,线程停止60s,以便于服务器恢复到完美状态

四、结果分析

This is ApacheBench, Version 2.3 <$Revision: 1879490 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking example.com (be patient) Completed 1 requests Finished 1 requests Server Software:       Apache Server Hostname:       example.com Server Port:           80 Document Path:         / Document Length:       44 bytes Concurrency Level:     1 Time taken for tests:   0.123 seconds Complete requests:     1 Failed requests:       0 Total transferred:     1234 bytes HTML transferred:       44 bytes Requests per second:   8.13 [#/sec] (mean) Time per request:       123.00 [ms] (mean) Time per request:       123.00 [ms] (mean, across all concurrent requests) Transfer rate:         9.84 [Kbytes/sec] received Connection Times (ms)             min mean[+/-sd] median   max Connect:       1   2   1.0     2       3 Processing:     5   20   5.0     19     30 Waiting:       4   18   4.5     17     28 Total:         6   22   5.5     21     35 Percentage of the requests served within a certain time (ms) 50%   21 66%   23 75%   25 80%   26 90%   28 95%   30 98%   32 99%   34 100%   35 (longest request) Server Software: 服务器软件名称。 Server Hostname: 服务器主机名。 Server Port: 服务器端口号。 Document Path: 请求的文档路径。 Document Length: 响应文档的长度。 Concurrency Level: 并发数。 Time taken for tests: 完成所有请求所花费的总时间。 Complete requests: 成功完成的请求数。 Failed requests: 失败的请求数。 Total transferred: 总共传输的数据量。 HTML transferred: 传输的HTML数据量。 Requests per second: 每秒处理的请求数。 Time per request: 每个请求的平均响应时间。 Time per request (mean, across all concurrent requests): 所有并发请求的平均响应时间。 Transfer rate: 数据传输速率。 Connection Times: 连接时间的统计数据,包括最小值、平均值、标准差、中位数和最大值。 Percentage of the requests served within a certain time: 请求在特定时间内完成的百分比。

ok 这就是ab压测的完整过程了 随时欢迎提问

1 打赏
打赏 20 积分后可见