使用LoadRunner对RESTful API进行压力测试需要按照从脚本开发、场景设计、执行监控到结果分析的全流程。
一、测试准备和需求分析
确定测试目标:确定要压测的API接口、预期并发数、吞吐量目的(TPS)、响应时间上限(如95%请求在500ms内)。
接口文档研读:获取API的URL、请求方法(GET/POST/PUT/DELETE)、请求头(如Content-Type: application/json、Authorization: Bearer <token>)、请求体结构、响应数据结构及状态码。
环境准备:确定测试环境和生产环境避免测试造成事故。在Controller所在机器部署LoadRunner,保证能访问被测API服务器。如果需监控服务器资源,提前配置好监控账号和防火墙规则。
二、VuGen脚本开发
打开Virtual User Generator(VuGen),选择 Web的HTTP/HTML协议(RESTful API根据HTTP,完全适用)。可录制、手动编写或导入API定义(如Postman集合、Swagger)生成骨架脚本。
1. 脚本结构以POST请求创建用户为例
c
Action()
{
/* 设置思考时间(可选,模拟真实用户延迟) */
lr_think_time(2);
/* 关联:如果需先从响应中提取token等数据,使用web_reg_save_param */
web_reg_save_param("authToken",
"LB=\"token\":\"",
"RB=\"",
"Ord=1",
"Search=Body",
LAST);
/* 登录请求获取token(如果需要) */
web_custom_request("Login",
"URL=https://api.zmtests.com/login",
"Method=POST",
"Resource=0",
"EncType=application/json",
"Body={\"username\":\"testuser\",\"password\":\"testpass\"}",
LAST);
/* 事务开始,用于测量重要业务 */
lr_start_transaction("CreateUser");
/* 检查点,证实业务成功 */
web_reg_find("Text=201 Created",
"Search=Headers",
"SaveCount=create_success",
LAST);
/* 添加JSON请求头 */
web_add_header("Content-Type", "application/json");
web_add_header("Authorization", lr_eval_string("Bearer {authToken}"));
/* 发送RESTful POST请求,使用参数化数据 */
web_custom_request("CreateUser",
"URL=https://api.example.com/users",
"Method=POST",
"Resource=0",
"EncType=application/json",
"Body={\"name\":\"{p_name}\",\"email\":\"{p_email}\",\"role\":\"user\"}",
LAST);
/* 检查事务结果 */
if (atoi(lr_eval_string("{create_success}")) > 0) {
lr_end_transaction("CreateUser", LR_PASS);
} else {
lr_end_transaction("CreateUser", LR_FAIL);
}
return 0;
}
2. 详解
请求发送:使用web_custom_request函数,需指定Method(如GET、POST、PUT等)、EncType为application/json,并将JSON格式的请求体放入Body参数。GET请求可省略Body。
参数化:将可变数据(用户名、邮箱等)替换为参数{p_name}、{p_email}。创建参数文件(如users.dat)并在VuGen中配置:打开参数列表(Ctrl+L),新建参数,选择File类型,浏览文件并设置列分隔符、取值方式(Sequential/Random/Unique)、更新频率(Each iteration/Each occurrence/Once)。
关联(动态数据处理):如果API需要会话Token、CSRF Token或从响应中提取ID用于后续请求,使用web_reg_save_param在请求前注册边界。上例中提取登录返回的token,存入参数authToken,后续通过lr_eval_string("{authToken}")引用。
检查点(业务测试):不能仅依赖HTTP状态码,需证实响应内容。web_reg_find可搜索响应头或主体中的特定文本,并记录出现次数。根据SaveCount判断事务成败,保证测试结果反映真实业务成功率。
事务和思考时间:用lr_start_transaction和lr_end_transaction包裹重要请求,得到准确的单次API调用耗时。思考时间(lr_think_time)可模拟客户端延迟,在压力测试中一般设小或移除(场景里可统一设置忽略思考时间来直接加压)。
JSON复杂请求处理:如果请求体很长或需要动态构造,可在脚本中用C语言拼接字符串,或使用lr_save_string创建JSON。注意转义双引号。
三、脚本调试和单用户测试
在VuGen中回放脚本,查看回放日志(Replay Log)和运行结果:
确定HTTP返回码是不是符合预期。
证实检查点是不是成功,事务状态是不是通过。
参数取值是不是正确,关联参数是不是提取到值。
如果失败,分析服务器返回的错误信息,调整请求头、参数或边界。
可通过Runtime Settings调整运行思路:
Run Logic:设置Action迭代次数,模拟单个用户多次调用。
Think Time:设置为“Ignore think time”以便快速证实,或“Replay think time”模拟真实间隔。
Log:调试时开启扩展日志(Extended log)以查看请求和响应详细数据,确定无误后改为标准日志,避免磁盘I/O影响压测。
四、Controller场景设计
脚本调试通过后,进入Controller(控制台)创建测试场景。
导入脚本:新建场景,选择刚才的脚本,设置脚本途径和运行时设置。
负载生成器(Load Generators):添加用于产生负载的机器(可为本机或多台远程机器)。在“Generators”中添加主机名/IP,并进行连接测试。
虚拟用户分配:按百分比或绝对数量将Vuser分配到不同Load Generator上。如果单个Generator内存/CPU不足,需分散负载。
场景方式:
手动场景:可精细控制Vuser的启动、不断和停止方式。
面向目的场景:设定目的(如每秒事务数达到1000),由LoadRunner自动调整Vuser数量。
调度设置(Schedule):
Ramp Up:启动方式(如每15秒启动5个Vuser),避免瞬间冲击。
Duration:不断运行时间(如30分钟),模拟稳定的压力状态。
Ramp Down:逐步停止,避免突然结束导致监控数据缺失。
运行时设置:
可包括VuGen中的日志级别(建议错误日志)、思考时间(一般选择“Ignore”或“Limit”)。
设置网络速度模拟(如WAN/LAN,如果测试API一般不限速)。
添加集合点(Rendezvous)以制造并发尖峰:在脚本中需要并发的位置插入lr_rendezvous,在Controller中启用方法(如等待所有Vuser到齐后释放)。
监控配置:
Windows/Linux服务器资源:添加被测服务器的CPU、内存、磁盘IO、网络等计数器。需有管理员权限或SNMP配置。
应用服务器/数据库:如有条件,通过LoadRunner自带的监控插件或自定义监控器采集队列长度、连接数等标准。
场景运行状态:默认记录每秒事务数、响应时间、吞吐量等。
五、执行测试和实时观察
启动场景后,在Controller的Run视图实时监控:
Vuser状态:查看是不是有失败、错误。
事务图表:观察平均响应时间曲线是不是随负载增大而平滑上升,有无剧烈波动。
吞吐量和点击率:API测试中,吞吐量(字节/秒)和每秒请求数应和虚拟用户数趋势一致。
服务器资源:如果CPU使用率不断超过90%或内存不断增长,可能成为短板。
错误统计:重视Errors per Second,及时分析错误码(如5xx服务端错误、4xx客户端错误、超时错误)。出现大面积失败时应停止测试,排查原因。
建议先进行负载测试(逐步增加Vuser直到达到目的并发,观察是不是满足标准),再视情况执行压力测试(不断增加负载直到系统崩溃,寻找极限点)或稳定性测试(长时间运行目的并发,检测内存泄漏等)。
六、报告结果分析
场景结束后,打开Analysis(分析器),LoadRunner会自动生成汇总报告。分析标准:
事务摘要:查看各事务的通过/失败数、最小/平均/最大/90%响应时间、标准差。重点重视平均响应时间和90%分位数(更好地反映大多数用户体验)。如果某事务失败率高,点击错误详情向下钻取。
每秒事务数(TPS)和响应时间关联图:将两者放在同一图表,观察负载上升时响应时间的拐点。拐点之前的吞吐量为最大有效吞吐量。
Web资源细分:如Web Page Diagnostics分解DNS分析、连接建立、首字节时间和接收时间。对于API,一般重视Time to First Buffer(服务器处理时间)和接收时间。
服务器资源和性能对比:把CPU、内存、磁盘队列和事务响应时间、吞吐量叠加分析。如发现响应时间突增时CPU已达100%,表示计算资源是短板;如果CPU低但响应时间长,可能数据库或外部服务慢。
合并报告和自动生成:可自定义图表、添加注释,使用“Export to HTML/Word”生成正式测试报告,附上结果和优化建议。
常见RESTful API性能短板:
服务端线程池不足导致排队。
数据库慢查询、缺少索引。
中间件(如Nginx、网关)连接数限制。
负载均衡方法不均。
客户端等待超时设置不当。
七、注意事项
JSON特殊字符:如果请求体含有双引号、反斜杠,需用\"或\\转义。建议将整个Body放入外部文件,使用lr_read_file动态读取,避免转义错误。
数据唯一性:如果业务要求参数唯一(如用户名),参数文件应足够大,且取值方式设为Unique,并设置“Continue in a cyclic manner”或“Abort Vuser”方法。
清理数据:测试可能产生大量垃圾数据,可事先准备删除脚本或使用独立测试数据库并在事后还原。
避免本地短板:Load Generator自身可能先达到短板(CPU、端口数),可在Windows上修改注册表增加临时端口范围(MaxUserPort)和缩短TIME_WAIT时间。监控Generator资源,必要时增加机器。
加密和认证:如果API使用OAuth2/JWT,需在脚本中实现获取Token的思路,并处理Token过期刷新(如通过if语句检查错误码后重新获取)。
版本控制:将脚本、场景文件纳入版本管理,便于复现和迭代。
通过以上流程可以系统化地使用LoadRunner完成RESTful API的压力测试,输出准确的容量测试报告,为系统优化提供数据支撑。