资讯动态

LoadRunner压测实战复盘:从脚本录制到瓶颈定位

发布时间:2026/9/20 15:23:51 来源:尧图企业网站定制
简介这是一份围绕性能测试工具LoadRunner完成的实验报告主要面向软件测试初学者、高校学生以及需要开展性能测试实践的工程师。报告从实验目的、内容与要求入手系统梳理了LoadRunner的四大工作环节Virtual User Generator脚本录制、Controller场景调度、运行测试和结果分析。在具体操作部分报告详细说明了录制Mercury Tours网上订票系统脚本、设置事务与集合点、实施参数化处理以及查看测试结果的方法能够帮助读者掌握并发用户模拟、响应时间和吞吐量分析等关键技能。资源包共含1个docx文档大小约1.83MB结构完整既是规范的实验报告范例也是性能测试入门的实用笔记。目前已有1872人学习下载适合需要快速上手LoadRunner并输出专业测试报告的读者也可作为后续实际性能测试项目的参考资料。LoadRunner 压测实战复盘从脚本录制到瓶颈定位的一次完整实验最近团队在做一套会员积分系统的上线前压测我负责用 LoadRunner 把整个链路扛一遍。这套系统不算复杂但牵扯到登录态、积分发放异步任务和数据库读写稍微有点并发就容易出幺蛾子。这篇文章就是把这次 LoadRunner 测试实验的完整过程做一个记录与复盘从环境准备到结果分析、再到常见的坑和排查思路尽量把关键细节讲透。不管你是刚接触 LoadRunner 的小白还是已经写过不少脚本的老手这次实验里涉及的脚本设计、参数化、场景配置和监控方法应该都能给你一些可复用的参考。1. 测试需求理解与整体方案设计1.1 被测系统背景与核心业务链路这次压测的目标是一套积分会员系统核心流程是用户登录、浏览商品、提交订单、触发积分发放。业务上最关注的是提交订单和积分入账这两个环节因为涉及数据库写入和异步任务压力一大就可能在事务提交或消息队列消费上出问题。系统架构大致是Nginx 做负载均衡后面挂了两台应用服务器数据库用的是 MySQL 主从部署积分发放通过 RabbitMQ 异步处理。整个链路中用户量峰值大约在 5 万左右日常峰值 TPS 大约 300 到 500这次压测目标是把核心接口压到 1000 TPS同时保证平均响应时间不超过 300ms错误率低于 0.1%。1.2 方案选型为什么还是选择 LoadRunner虽然现在市面上一堆开源工具比如 JMeter、Gatling 都很流行但这次我还是选了 LoadRunner原因有三个。第一LoadRunner 的脚本录制能力在应对复杂协议时仍然能省不少事。积分系统里有不少前端异步请求尤其是订单提交后前端会轮询积分状态这类请求用 JMeter 手动抓包再构造比较麻烦而 LoadRunner 通过录制能直接帮你生成脚本框架特别是 Web HTTP/HTML 协议下对 AJAX 请求的处理很成熟。第二LoadRunner 的场景设计更贴近真实业务模型。它可以方便地设置集合点、思考时间、阶梯加压并且能在同一场景里混合多个脚本模拟不同用户行为这对业务模型复杂的系统非常重要。第三团队里其他成员对 LoadRunner 更熟悉项目周期紧、没有太多时间让所有人重新学习一套新工具。从工程化的角度用团队已有的技术栈比追新工具更有性价比。1.3 实验环境与工具版本说明压测机是一台 16 核 32G 内存的物理机Windows Server 2019装了 LoadRunner 2023 社区版。被测服务器是两台 8 核 16G 的云主机数据库单独跑在一台 8 核 32G 的机器上。需要留意的是压测机能提供的并发连接数受操作系统端口和文件句柄限制Windows 系统默认的动态端口范围有限压测前需要手动调大。LoadRunner 2023 的安装包可以直接从官方渠道获取社区版功能完整但限制了虚拟用户总数对于多数中小项目的压测场景已经足够。如果之前装过旧版本建议彻底卸载干净再重装否则经常会出现录制时 Agent 进程启动失败的问题。2. 脚本开发与关键技术点处理2.1 录制策略与脚本结构规划我用 VuGen 录制了一个典型的用户购买流程登录、浏览商品列表、查看商品详情、加入购物车、提交订单、积分查询。录制完成后脚本里会生成大量请求但真正做压测时不需要把每个请求都保留那样只会无谓消耗压测机的资源。我的做法是先梳理出关键请求再删掉冗余请求。这个系统的核心请求大概是这几个POST /api/user/login登录接口GET /api/product/list商品列表POST /api/order/create提交订单GET /api/point/status积分状态查询删掉图片、CSS、JS 等静态资源请求。注意如果系统静态资源和动态接口共用域名录制时这些请求会混在一起要用 VuGen 的过滤功能或者在录制前在录制选项中设置 URL Filter排除常见静态资源扩展名。2.2 参数化让每次请求都不重样如果压测时所有用户都提交完全相同的数据那测出来的结果没有任何参考价值因为真实场景里每个用户的数据都不一样数据库的索引选择、缓存命中率都会有很大差异。所以参数化是压测脚本中最重要的一步。我在登录接口上做了账号参数化从之前准备好的测试账号池里取数据// 从账号数据文件中随机读取一行 char username[64]; char password[64]; int row rand() % 500; lr_save_string(lr_eval_string({account_username}), param_username); lr_save_string(lr_eval_string({account_password}), param_password);在 VuGen 的参数属性里我把账号和密码分别设成两个参数文件参数更新方式选每次迭代随机。这里有一个细节如果选择了每次出现随机同一个用户在同一个脚本里可能出现两次登录用了不同账号的情况这在真实场景里不常见。所以我一般选每次迭代随机保证一次迭代内同一个用户身份一致。商品 ID 也做了参数化基本思路一样从商品表里导出几百个真实商品 ID随机取用。2.3 关联甩掉写死的 token登录接口会返回一个 token后续所有请求的请求头里都需要带这个 token。录制时这个 token 是写死的如果不做关联回放时就会因为 token 过期或无效而全部失败。在 LoadRunner 里做关联有几种方式最常用的是 Web Reg Save Param 函数配合正则表达式。我在登录请求前加了这样的代码// 定义关联规则 web_reg_save_param( ParamNametoken_param, LBaccess_token\\\:\\\, RB\\\, SearchBody, LAST );需要注意的是LoadRunner 函数里的转义和正则表达式容易把人绕晕。我的经验是先在录制好的脚本里找到登录响应示例提取出 token 左右边界再小心地写转义。如果响应体较大建议加上 SearchBody 限定搜索范围效率更高。写完后在后继请求的 Header 里引用web_add_header(Authorization, Bearer {token_param});回放一次确认 token 能成功传递。调试关联时常用的是 VuGen 的快照对比功能比较录制时的响应和回放时的响应如果 token 相关位置显示红色差异说明关联规则还需要调整。2.4 事务、集合点与思考时间的合理配置事务是 LoadRunner 统计响应时间的基本单位我按业务操作拆分了几个事务login_transaction、order_create_transaction、point_query_transaction。事务的起始点必须是用户真正发起请求的那一行不要把思考时间包在事务里。集合点用于模拟多个用户同时操作比如我要压提交订单这个操作在高并发下的表现就在提交订单请求前加一个集合点lr_rendezvous(order_submit_rendezvous); lr_start_transaction(order_create_transaction);思考时间要不要加是个经常争论的话题。我的做法是基准测试不加思考时间直接压最大吞吐容量测试按业务模型加思考时间不然结果会过度悲观。这次实验因为目标是压满 1000 TPS所以在真实业务模型场景里加了 2 到 5 秒的随机思考时间在极限压测场景中去掉了。3. 场景设计与压力生成3.1 场景类型选择场景模式 vs 目标导向模式LoadRunner Controller 里提供了两种场景模式手动场景和面向目标场景。我这次先用手动场景做了一轮摸底测试再进行面向目标场景的容量探测。摸底测试的目的一是验证脚本稳定性二是大致确定系统瓶颈在哪个量级。摸底测试并发用户数从 50 开始逐步增加到 200、500每轮持续 5 分钟观察 TPS 和响应时间的变化。摸底结束后我创建了一个新的面向目标场景目标设为 1000 TPSLoadRunner 会自动调节虚拟用户数来逼近这个目标。这种模式的好处是它直接帮你把能不能达到目标 TPS这个问题变成一个可量化的指标而不是靠人工去猜到底要多少并发。3.2 Vuser 初始化与加载策略在场景设置里我设置了 Vuser 初始化方式为逐步初始化每 5 秒初始化 10 个用户。一次性把所有用户都初始化好虽然省时间但真实用户不是同一秒涌进来的而且瞬间初始化大量用户本身就会给压测机带来资源压力。加压策略我用了每 15 秒加载 20 个用户这样做的好处是系统压力的变化是渐进的你可以从监控曲线上清楚看到系统从稳定到出现拐点的过程。如果一下子加 500 个用户很可能压力已经打满但你没看到拐点窗口后续定位问题就少了很多关键信息。退出策略稍微激进一些每 5 秒退出 50 个用户。这是为了让场景尽快结束减少对生产环境的压测时间窗口。3.3 Linux 服务器资源监控配置LoadRunner 可以监控 Unix/Linux 服务器的资源但需要在被测服务器上启用 rstatd 服务。这个过程有点繁琐而且有些云主机默认没有这个服务需要手动安装。我直接用 LoadRunner 自带的 SiteScope 监控应用服务器和数据库服务器的 CPU、内存、磁盘 IO。如果不想折腾 SiteScope也可以在 Linux 上用 nmon 或 dstat 把监控数据记录成文件压测结束后再对比分析。从实际效果来看LoadRunner 内置的监控图表虽然做得很一般但是把数据集中在一起看还是方便很多尤其是把 TPS、响应时间、CPU 使用率画在同一个时间轴上能一眼看出瓶颈和资源使用之间的关联。4. 执行过程中的问题与排查思路4.1 错误类型速查从大量实验里总结的对照表压测过程中 LoadRunner 会记录大量错误很多新手一看到错误就慌了。这里分享一份我自己整理的常见错误对照表基本覆盖了这次实验和以往项目中遇到的高频问题错误信息可能原因解决方向Connection reset by peer服务器端主动断开连接可能是超时或并发限制检查应用服务器线程池和数据库连接池大小Timed out请求超过预设超时时间优先查慢 SQL和第三方接口而不是盲目加大超时Failed to connect to server压测机到服务器网络不通或连接数耗尽检查防火墙和压测机端口范围设置The socket was disconnected中间设备Nginx/防火墙断连检查 keepalive 配置和连接超时时间No such file or directory参数文件路径错误在 VuGen 里使用绝对路径或把参数文件放到脚本目录下Memory allocation error压测机内存不足降低 Vuser 数或者拆分场景分批次压测404/401 响应接口路径/权限问题检查请求头和 URL 分段确认是否需要鉴权这次实验里出现的错误大多集中在连接被重置和超时两类。排查时我先把错误按时间线分段和流量加压曲线放在一起看。比如在 500 并发以前几乎没有错误到了 700 并发时开始出现 Connection reset说明瓶颈点大概率在连接处理能力上而不是业务逻辑本身。4.2 压测机 Windows 端口耗尽问题第一次跑 500 并发场景时LoadRunner 日志里出现了大量 Failed to connect to server但被测服务器的 CPU 和内存使用率都不高说明问题出在压测机这一端。排查下来是 Windows 系统的动态端口范围太小。默认情况下 Windows 的动态端口范围是从 49152 到 65535大约 16000 个端口但连接被 TIME_WAIT 状态占用时可用端口数量会迅速下降。压测机的所有虚拟用户、所有连接都共用这些端口很快就用完了。解决办法是用管理员权限执行netsh int ipv4 set dynamicport tcp start1025 num64511 netsh int ipv4 set dynamicport udp start1025 num64511调整后重启系统生效。改完之后同样 500 并发的场景里连接失败的错误立刻消失了。这是 LoadRunner 压测中特别容易忽略但影响很大的一个细节。4.3 数据库连接池瓶颈定位TPS 加到 700 左右时响应时间开始从 80ms 飙到 800ms 以上。从 LoadRunner 的监控图表看应用服务器 CPU 只有 50% 左右问题看起来不在应用层。打开数据库监控后发现数据库连接数已经打满大量连接在等待状态。进一步排查发现应用服务器配置的数据库连接池最大连接数是 100而当时 700 并发下应用需要同时打开的连接数早就超过 100 了。连接池满后新的数据库请求只能排队等待响应时间自然急剧上升。解决办法是调大连接池大小从 100 调整到 300。同时提醒开发团队检查是否有连接泄漏的情况压测时观察连接数曲线确认调整后连接数在 300 以内有富余并且没有持续上升的迹象。调整后再次执行同样的场景TPS 顺利突破 1000响应时间稳定在 220ms 左右。5. 测试结果分析与性能调优5.1 关键指标解读TPS、响应时间与资源利用率整个实验跑完核心指标数据整理如下指标目标值实际值结论TPS10001045达标平均响应时间≤300ms220ms达标90 分位响应时间≤500ms410ms达标错误率0.1%0.02%达标应用服务器 CPU80%68%达标数据库 CPU80%75%接近瓶颈单独看每个指标都达标了但数据库 CPU 的 75% 值得警惕。这说明当前架构下数据库是率先接近上限的组件。如果未来业务增长可能需要考虑读写分离的进一步优化或者把积分发放这类非核心链路做更彻底的异步化避免高峰时段和核心交易链路争抢数据库资源。5.2 用 Analysis 报告定位瓶颈层级LoadRunner Analysis 生成的报告里我最常看的是三个图事务响应时间曲线、每秒点击数、每秒 TPS。把这三张图重叠对比有一个很实用的排查方法如果每秒点击数在增长但 TPS 不再增长说明服务器处理能力到了上限瓶颈在服务端如果两者同时下降说明加压端出了问题比如压测机连接耗尽或脚本执行出错。这次实验里TPS 从 800 往 1000 爬升的过程中点击数还在涨TPS 增速却在放缓而数据库 CPU 已经快要打满说明服务端资源确实是瓶颈。之后再通过拆分接口耗时确认慢在数据库查询上。整个链路定位花费的时间不长关键在于先把负载生成端的干扰排除掉再去查服务端。5.3 调优措施与二次验证针对发现的问题开发团队做了三处调优数据库连接池从 100 调到 300优化了订单查询 SQL原来有一条子查询走了全表扫描加索引后查询耗时从 180ms 降到 30msNginx 的 keepalive_timeout 从 65 秒调到 30 秒减少空闲连接占用。重新跑一轮同样的压测场景TPS 稳定在 1040 左右数据库 CPU 下降到了 75% 以内。实验目标达成。6. 实验复盘与经验沉淀6.1 实验过程中踩过的坑汇总这次实验从头到尾踩坑主要集中在四个方面。第一个坑是脚本关联规则写错导致 token 一直取不到回放成功率只有 30% 左右。排查方法是打开回放日志搜索 token 关键字发现左右边界字符串里少了一个反斜杠。用 Web Reg Save Param 做关联时边界字符串里的引号和反斜杠必须转义建议平时在这个函数上多花点时间因为它直接决定脚本能不能用。第二个坑是 Windows 系统端口耗尽。这个问题在上面已经详细说了关键是在压测前就检查压测机的端口配置不要等到错误暴增再回头查。第三个坑是参数文件数据量不足。我准备了 500 个测试账号但参数化方式是每次迭代随机结果跑高并发时大量用户随机到同一个账号导致同一账号反复登录登录接口出现锁冲突。后来把账号数扩展到 2000 个并且改成每次迭代顺序读取问题消失。第四个坑是场景退出阶段的数据不一致。我设置退出策略时每 5 秒退出 50 个用户但部分用户还在事务执行中就强制退出了导致订单数据不完整。后来在 Run-Time Settings 里勾选了Continue on error并且把当虚拟用户出错时的处理方式改为继续运行避免因个别错误导致整个用户中断。6.2 LoadRunner 脚本调试的几个实用技巧写脚本阶段有几个小技巧能大幅提升效率。切换到树形视图查看录制的每一步请求可以快速掌握请求的 URL、参数、响应结构比直接看代码清晰得多。录制完成后不要急着删请求先用树形视图定位每个请求的用途再批量删除静态资源请求。回放时遇到报错优先看 Replay Log 里的Error级别信息。如果报错信息不够清楚可以在代码里临时加 lr_output_message 函数打印关键参数值比如登录后打印返回的 token能快速确认关联是否成功。另外VuGen 的快照对比是个调试神器。回放成功后对比录制快照和回放快照的差异凡是请求 URL 里带时间戳、随机数的地方都可能是需要关联或者额外参数化的位置。这套方法找动态参数特别准比手动看脚本高效得多。6.3 实验的可扩展方向与后续计划这次实验做完后整个测试组对这套积分系统的性能容量有了一个清晰的基线。后续几件事是我计划在下一轮迭代里继续推进的引入Appium做移动端接口层的自动化回归把会员积分相关的核心链路固化到 CI/CD 流水线里每次发版前自动跑一遍冒烟压测结合已有的自动化测试平台把这次压测脚本和监控数据接入到统一的测试报告系统里形成历史趋势分析这样每次性能波动都能有据可查在测试环境里引入更细粒度的链路追踪配合 LoadRunner 的事务结果把接口层耗时分到应用、数据库、缓存、消息队列各层进一步缩短未来瓶颈排查的时间。当然这些计划都需要团队资源和时间投入。但如果说这次 LoadRunner 实验给我最深的感受那就是性能测试最值钱的不是工具操作本身而是从数据里读出系统短板、并且能推动问题闭环解决的能力。工具只是手段把整个排查优化链路跑通才是压测真正有价值的地方。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价