简介:「LoadRunner性能测试报告.doc」是面向软件测试学习者与性能测试入门者的实战报告文档,围绕 HP Web Tours 在线订票系统展开完整性能测试实践。内容涵盖系统三层架构与功能模块说明、登录—浏览—加购—结算—支付的业务流程梳理、登录验证与数据库查询及支付处理等关键测试点,以及测试环境配置;并给出吞吐量、响应时间、并发用户负载、CPU 与内存资源利用率等指标的测试方法与期望值,通过 Vuser 脚本模拟不同负载级别,记录运行状况与测试场景数据,最终输出结果分析与数据库查询优化、代码结构调整等改进建议。资源包共 1 个 doc 文件,约 677KB,结构与目录清晰,可直接作为课程实训报告模板或性能测试流程参考。目前已有 1304 人学习下载,适合需要熟悉 LoadRunner 测试流程、报告撰写与性能瓶颈分析思路的读者。
1. 从一份性能测试报告反向校验 LoadRunner 的压测设计
一份性能测试报告里最容易骗人的地方,往往不是那些炫目的图表,而是“跑了两轮就好了”这类叙述。HP Web Tours 订票系统的被测对象核心只有注册、登录、查询航班三个动作,但当 200 个并发用户同时压上来,AP 服务器 CPU 直接顶到 100%,数据库侧 IO 等待居高不下,Audit_Transaction 响应时间飙到 190 秒——问题不一定出在业务逻辑,很可能出在脚本流程和场景设计上,尤其是“登录”这件事有没有按真实用户习惯处理。
这份报告两次执行的差异只有一处:第一次每笔交易都重新登录,第二次每个 Vuser 只登录一次、后续交易复用会话。结果第一次跑到 30 分钟就因登录超时连锁失败被迫中止,第二次稳定跑满 50 分钟。这说明 LoadRunner 这类工具只是放大器,脚本结构决定了你测的是系统能力,还是自己制造出来的排队。下面按脚本录制、事务划分、场景设计、指标采集、慢事务定位的顺序拆开,适合正在写性能测试报告,或者刚跑完 LoadRunner 但对着数据没底的人。
2. Vuser 脚本录制与事务划分:登录、查询航班怎么拆才合理
LoadRunner 的脚本是后续所有场景和报告的地基。脚本录得粗,事务边界划得乱,后面加再漂亮的图表也是错的。HP Web Tours 的三个核心交易——注册、登录、查询航班——每个的录制方式和事务切法都不一样,需要单独处理。
2.1 协议选型与 HTTP/HTML 录制模式
HP Web Tours 是典型 B/S 系统,客户端通过浏览器访问,选Web (HTTP/HTML)协议即可。VuGen 新建脚本时勾选该协议,录制级别建议用基于 HTML 的脚本,而不是 URL 模式。原因是 HTML 模式下 LoadRunner 会把一个页面里所有资源请求自动合成一条web_url或web_submit_data,脚本可读性和可维护性都更好;URL 模式会把每个 gif、js 都录成独立请求,后期回放容易因静态资源变动而误报失败。
录制时容易踩的两个坑:一是浏览器代理设置冲突,常见做法是先关掉本地浏览器代理,录制完成后再恢复;二是录制过程中 View State、Session ID 这类动态值会被硬编码进脚本,直接回放必然失败,必须在录制后用关联(Correlation)替换。
2.2 事务边界:登录、查询分别是一笔还是两笔
事务(Transaction)的粒度直接决定报告里响应时间的含义。这份报告里登录和查询航班被拆成独立事务,是合理的,因为两者在业务上对应不同的用户动作,在性能上瓶颈也往往落在不同层。脚本里用lr_start_transaction/lr_end_transaction包裹:
Action() { // 静态资源无需单独计事务 web_url("WebTours", "URL=http://192.168.1.100:1080/WebTours/", "Resource=0", "RecContentType=text/html", "Snapshot=t1.inf", "Mode=HTTP", LAST); // 登录事务边界:从提交登录表单到跳转首页 lr_start_transaction("login_transaction"); web_submit_data("login.pl", "Action=http://192.168.1.100:1080/WebTours/login.pl", "Method=POST", "RecContentType=text/html", "Referer=http://192.168.1.100:1080/WebTours/nav.pl?in=home", "Snapshot=t2.inf", "Mode=HTTP", ITEMDATA, "Name=userSession", "Value={userSession}", ENDITEM, "Name=username", "Value={username}", ENDITEM, "Name=password", "Value={password}", ENDITEM, "Name=login.x", "Value=52", ENDITEM, "Name=login.y", "Value=10", ENDITEM, LAST); // 用检查点确认登录真的成功,而不是拿到了错误页 web_reg_find("Text=Welcome", "SaveCount=login_count", LAST); lr_end_transaction("login_transaction", LR_AUTO); return 0; }逻辑说明:lr_start_transaction与lr_end_transaction之间是事务的计时区间,只有这段区间内的服务器处理时间才会被计入响应时间。LR_AUTO表示由 LoadRunner 自动判定事务通过还是失败。检查点web_reg_find必须注册在请求之前,否则无法拦截响应内容。
参数说明:Resource=0表示这条请求不计入页面资源统计,仅作为页面跳转;Snapshot用于回放失败时定位问题,可以保留;Mode=HTTP是录制时的默认模式,与 HTML 单元回放兼容。
提示:事务名不要用中文,LoadRunner Controller 和 Analysis 对中文事务名的排序和筛选支持不稳定,用英文小写下划线是最省事的做法。
2.3 关联与参数化:userSession 和用户资料的处理
userSession是 HP Web Tours 每次登录后下发的动态值,硬编码回放必然失败,必须做关联。常见做法是在录制时打开“自动关联”,或者在脚本里手动加web_reg_save_param:
web_reg_save_param("userSession", "LB=name=\"userSession\" value=\"", "RB=\"", "Search=Body", LAST);LB和RB是左右边界,Search=Body指定只在响应正文里找。这个函数也必须放在产生该值的请求之前。
用户数据则用参数化,而不是每个 Vuser 硬编码一份账号密码。在 Parameter List 里建一个username参数表,用Unique+Once的组合,每个 Vuser 取一行,登录时用它填表单。这样 200 个并发用户就能模拟 200 个不同身份,避免服务端会话互踢。
2.4 回放验证与迭代次数确认
脚本写完先单用户回放,日志等级调到 Extended,逐条核对每个请求的返回码和检查点。确认无误后,把Run-time Settings里的 Run Logic 迭代次数设为 1,先跑通。注册和查询航班两段脚本在报告里对应不同的事务名,回放时应该分别看到login_transaction、register_transaction、query_transaction三条事务记录,任何一条缺失或超时都要回脚本里找原因,不要直接进 Controller 压测。
3. 场景设计:逐步加压、瞬间加压与 3 台 PC 的分工
脚本能在单机回放通过,只代表语法对了。真正决定报告可信度的,是 Controller 里的场景配置。这份报告做了 200、400、700、1000 四个用户档位,但真正跑出结果的是 200 并发那一档,其配置思路值得展开。
3.1 手动场景还是目标场景
Controller 提供两种场景模型:手动场景(Manual Scenario)和目标场景(Goal-Oriented Scenario)。目标场景是设定一个目标(如 TPS 达到 100 或响应时间稳定在 5 秒内),由工具自动调节并发用户数去逼近,适合验收类测试;手动场景是用户数、加压节奏、持续时间全部手工指定,适合找瓶颈。
这份报告用的是手动场景,因为目的是“看系统在多大的压力下崩”,而不是“验证系统能不能扛住 500 TPS”。两种场景在分析阶段的意义不同:手动场景跑出来的吞吐曲线能让你看到拐点,目标场景只能告诉你目标达成没达成。
3.2 加压节奏:逐步加压和瞬间加压怎么选
报告里提到两种加压方式:每隔 2 秒启动 1 个 Vuser,以及一次性启动 10 个或 100 个。这两种方式在 Controller 里分别对应 Ramp-up 配置:
| 加压方式 | Controller 配置 | 适用场景 | 观察重点 |
|---|---|---|---|
| 逐步加压 | Ramp-up 每 2 秒启动 1 Vuser | 找系统稳定吞吐上限 | TPS 拐点和响应时间跃变 |
| 瞬时加压 | Ramp-up 设为 0,同时启动 | 模拟突发流量、开机洪峰 | 短时错误率和恢复速度 |
| 阶梯加压 | 分批设置,每批 50 用户 | 定位在哪个并发量开始劣化 | 各档位资源利用率对比 |
逐步加压能明确看到“在多少用户数之后响应时间开始指数上升”,这个拐点比最大 TPS 更有价值。瞬间加压则更考验连接池、线程池、数据库连接数的初值设置是否合理,短时间内的错误率会显著高于逐步加压。
3.3 分布式负载生成器的部署与分配
报告里用了 3 台 PC 承载 200 个并发用户,两台各 70 左右,一台 60 左右并同时跑 Controller。这种部署在中小规模压测里非常常见,但有两条硬约束要注意:
- 每台负载机(Load Generator)能承载的 Vuser 数受 CPU、内存和网络带宽限制。跑 Web (HTTP/HTML) 协议时,单台 4 核 8G 的机器大概能稳定跑 80~120 个 Vuser,具体要看每个 Vuser 的脚本复杂度。
- Controller 所在机器同时跑 Vuser 会拉高自身 CPU,影响加压精度,能分开就分开。
负载机在 Controller 里通过Load Generators面板添加,IP 填内网地址,连接方式选默认的Agent或Remote Management,每台机器要预装 LoadRunner Agent 并启动服务,Windows 上防火墙需放行对应端口。配置完成后点Connect,状态全绿才算就绪。
3.4 场景运行与实时监控的采集项
Controller 的Run视图里需要打开几个关键图:Running Vusers(当前并发数)、Transactions per Second(TPS)、Average Transaction Response Time(平均响应时间)、Errors per Second(错误数)。
AP 服务器和 DB 服务器的资源指标,用 LoadRunner 自带的Web Resource Monitor或Windows Resource Monitor采集 CPU、Memory、Disk 计数器。这次报告里能拿出User% / Sys% / Wait%的三段数据,就是因为提前在 Controller 里配好了 Windows 资源监控,指向了两台主机的性能计数器。没配这一层,后面分析就只能看业务层,找不出到底是 CPU 满还是 IO 排队。
3.5 场景持续时间与失败退出策略
200 并发逐步加压大约 7 分钟到满,报告里第一次跑了 30 分钟就崩,是因为没有配事务失败比例触发停止。常见做法是在 Controller 的Scenario Schedule里加一个Stop scenario if transaction failure percentage exceeds X%,比如设成 20%,一旦登录事务大面积超时,就能自动停在可分析的节点,而不是等它跑成一锅粥。第二次稳定跑到 50 分钟,是因为登录操作被提前收口,后面所有交易共用同一会话,脚本负载特征发生了根本变化。
4. 指标采集与瓶颈定位:从 AP 的 CPU 100% 拆到 DB 的 IO 等待
报告出来之后,最有价值的工作是回答三个问题:哪个事务慢、慢在哪一层、下一轮该改什么。把两次测试的数据摊开对照,答案就很清楚了。
4.1 业务级指标:响应时间、TPS、成功率
业务层指标从 Analysis 里直接取,三个口径必须说清楚:
- 平均响应时间:所有成功事务的平均值,容易被大量快事务拉低,配合 90% 分位或最大值一起看。
- TPS:单位时间内完成的事务数,注意区分“成功 TPS”和“发起 TPS”,报告里写的吞吐率应是成功交易量除以统计时段。
- 成功率:成功事务数除以发起事务数,报告里给的期望值是大于 95%,这个门槛对订票类业务是合理的。
第一次测试里 AutoUW_Transaction 平均响应 3.73 秒、最大 387.87 秒,这个最大值意味着链路里存在长时间的阻塞,不是简单的高负载排队。第二次测试里 GeneralQuery_Transaction 平均 11 秒、最大 35 秒,属于可接受的劣化。这种差异化才是分析要抓的重点。
4.2 系统级指标:AP 与 DB 两端的 CPU 与 IO 对照
报告里 AP 服务器两次都跑到 95% 以上,DB 服务器第一次 CPU 很低、IO 等待反而高,第二次 CPU 上到 75%。这个组合说明:
- 第一次 AP 满、DB 闲,说明瓶颈在应用层,登录操作过于频繁导致 AP 端的会话处理、加密校验吃掉了 CPU,业务请求根本到不了数据库。
- 第二次 AP 依然满、DB CPU 上升、IO 等待依然高,说明请求真正打到了数据库层,数据库成了第二段瓶颈,慢在物理 IO 上。
把 AP 和 DB 两端数据放在一张表里对照,比各画一张趋势图更能说服人:
| 阶段 | AP CPU | DB CPU | DB IO 等待 | 明显慢的事务 |
|---|---|---|---|---|
| 第一次(1:52–2:20) | ~100% | <20% | 较低 | 登录相关全部超时 |
| 第二次(2:45–4:00) | >95% | >75% | 较高 | Audit、ClaimRegister |
4.3 两次测试流程差异带来的数据解读
两次测试唯一的变量是登录流程,但因为登录是一个非常“重”的操作(会话创建、密码校验、跳转),它在 200 并发下的开销不可忽略。第一次每笔交易前都登录,相当于把登录的负载乘以了交易次数,AP 端 CPU 被反复叫醒做同一件事,事务成功率自然崩塌。
第二次改成每个 Vuser 只登录一次,登录开销从“每交易一次”变成“每 Vuser 一次”,AP 压力下降,请求真正到达数据库,于是 DB 端的 CPU 和 IO 都跟着上来了。从性能测试角度,第二次的结果才是有效结果;第一次只能作为“登录设计缺陷”的佐证。
注意:脚本流程变化后必须重新校准基线,否则两次数据之间没有可比性。报告里把两次结果并列展示是对的,但在结论里必须明确哪一次代表系统真实能力。
4.4 慢事务定位:Audit_Transaction 与 ClaimRegister_Transaction
第二次测试里最扎眼的是两类交易:Audit_Transaction 平均 162 秒、最大 207 秒;ClaimRegister_Transaction 平均 143 秒、最大 163 秒。这两个事务的响应时间在整段测试中始终居高不下,没有随登录完成而回落,说明它们的慢与并发数无关,是稳态慢事务。
排查这类事务的常用套路:
- 在 Analysis 里打开
Transaction Response Time (Percentile)图,确认慢的是所有采样点还是尾部少数点。如果 90% 分位也远高于平均,说明是脚本级的普遍慢;如果只是平均值被拖高,说明是长尾。 - 打开
Web Page Breakdown或Page Download Time Breakdown,看时间花在 First Buffer、Receive 还是 Client Time。如果 Client Time 占比高,问题可能在脚本本身的思考时间或参数化取数。 - 在 AP 端开数据库慢查询日志,把这两个事务对应的 SQL 抓出来,常见原因是缺索引、全表扫描或锁等待。
- 用
Web Resource Monitor对比这两个事务执行时段的 DB 锁资源数量,如果锁等待明显上升,说明事务隔离级别或提交时机有问题。
报告里提到这两个事务“超时严重、成功率很低”,基本可以判断它们卡在数据库层。下一轮调优应该先做 SQL 审查和索引补齐,而不是继续加机器。
5. 从报告到落地:登录复用、参数化与慢事务剥离的调优技巧
性能测试最终要回答的是“下一步怎么改”。HP Web Tours 这套流程跑过两轮之后,最值得复用的三个技巧是脚本层的登录复用、数据层的参数化隔离,以及报告层的慢事务单独分析。下面按可复现的粒度展开。
5.1 脚本层:登录只跑一次,交易循环复用会话
登录复用是最直接有效的一招。实现方式是在脚本里用vuser_init段执行登录,把userSession存到全局参数里,Action段循环执行查询或业务交易,不再重复登录:
vuser_init() { web_url("WebTours", "...", LAST); lr_start_transaction("login_transaction"); web_submit_data("login.pl", "...", LAST); lr_end_transaction("login_transaction", LR_AUTO); // userSession 通过关联存到参数,后续 Action 里复用 return 0; } Action() { // 复用初始化阶段拿到的 userSession,只循环发查询交易 lr_start_transaction("query_transaction"); web_submit_data("itinerary.pl", "...", LAST); lr_end_transaction("query_transaction", LR_AUTO); return 0; }这样每个 Vuser 只承担一次登录开销,报告中业务层响应时间更能反映真实业务能力。vuser_init在整个场景中每个 Vuser 只执行一次,Action才按迭代次数循环。
5.2 数据层:参数池按 Vuser 隔离,避免账号互踢
参数化时优先选Unique + Once的组合,每个 Vuser 从参数表里取一行独占使用,避免多个 Vuser 抢同一个账号导致服务端会话互斥。如果业务账号不够,可以退一步用 Unique + Each iteration,让每次迭代取不同的值,但要确认服务端允许多会话并存。参数表里建议额外加一列状态备注,压测完可以回溯哪个账号在哪个时段报错。
5.3 报告层:慢事务单独建图、单独下结论
分析时把慢事务从总体平均线里剥离出来单独建图。Analysis 里右键Add New Graph→Transaction Response Time,筛选出 Audit_Transaction、ClaimRegister_Transaction,再和Running Vusers双 Y 轴叠加,能直观看到它们的响应时间和并发数是否相关。如果两条曲线不平行,说明慢是业务本身的问题;如果平行上升,说明是资源竞争。最终报告里“平均响应时间 <15s、成功率 >95%”这类期望值必须按事务分别列出实测值,不能用一个总数概括全局,否则慢事务永远会被快事务的平均值掩盖。
本文还有配套的精品资源,点击获取