本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:LoadRunner是由Micro Focus开发的企业级负载与性能测试工具,广泛应用于系统稳定性评估、压力测试和容量规划。本系列视频教程“LoadRunner性能测试视频2”深入讲解LoadRunner的核心组件与工作流程,涵盖虚拟用户脚本录制、测试场景设计、性能指标监控及结果分析等关键内容。通过实际操作演示,帮助测试人员掌握VuGen脚本编写、Controller场景管理、Analyzer报告解读,并结合断言调试、异常处理与CI工具集成,提升自动化测试效率。教程强调最佳实践,助力IT专业人员构建高效、可靠的性能测试体系。
性能测试

1. LoadRunner核心概念与性能测试理论基础

1.1 LoadRunner核心组件架构与角色定位

LoadRunner由VuGen(虚拟用户生成器)、Controller(控制器)和Analysis(分析器)三大核心组件构成。VuGen负责脚本录制与开发,模拟用户操作行为;Controller用于设计负载场景并调度Load Generator执行虚拟用户任务;Analysis则对测试结果进行多维度数据可视化分析。三者协同实现“生成负载—执行测试—分析瓶颈”的完整闭环。

1.2 性能测试关键概念解析

虚拟用户(Vuser)是LoadRunner中模拟真实用户的最小执行单元,通过事务(Transaction)标记关键业务流程,如登录、下单等,用于度量响应时间。集合点(Rendezvous)用于同步多个Vuser,模拟瞬时高并发场景。Think Time模拟用户操作间隔,使负载更贴近真实行为。

1.3 性能测试流程与目标定义

典型性能测试流程包括需求分析、测试计划制定、脚本开发、场景设计、执行监控与结果评估六个阶段。核心性能指标涵盖响应时间(一般要求<3s)、吞吐量(TPS)、错误率(<0.5%)及系统资源利用率(CPU<75%,内存<80%),为后续章节的实践提供量化依据。

2. 虚拟用户技术原理与VuGen脚本开发实践

在现代性能测试中,模拟真实用户行为是验证系统可扩展性和稳定性的核心手段。LoadRunner通过“虚拟用户”(Virtual User, Vuser)机制实现对成千上万并发用户的精准模拟,而这一切的起点正是 VuGen(Virtual User Generator) 工具。VuGen 不仅负责录制和生成用户操作脚本,更承担了将原始交互转化为可编程、可参数化、可控制的自动化负载任务的关键角色。深入理解虚拟用户的工作机制以及掌握 VuGen 脚本的开发技巧,是构建高保真性能测试场景的前提。

本章聚焦于从底层运行模型到高级脚本优化的全过程,剖析 Vuser 如何在协议层模拟真实请求流,并通过 VuGen 实现复杂业务逻辑的建模。我们将逐层拆解其生命周期管理、协议适配逻辑、脚本录制策略、动态数据处理方法以及回放控制机制,帮助开发者与测试工程师构建既贴近现实又具备高度可控性的性能测试脚本体系。

2.1 虚拟用户(Vuser)的工作机制与运行模型

虚拟用户并非简单的线程或进程复制,而是基于特定通信协议封装的一整套状态机模型,能够在控制器调度下独立执行预定义的业务流程。每一个 Vuser 都代表一个逻辑上的终端用户,具备完整的上下文环境(如会话 ID、Cookie、认证令牌等),并通过协议栈与被测系统进行交互。这种设计使得 LoadRunner 能够以极低资源开销模拟大规模并发访问,远超物理机器所能承载的真实浏览器数量。

2.1.1 Vuser的生命周期管理:从初始化到执行再到关闭

Vuser 的生命周期遵循严格的三阶段模型: 初始化(init)→ 主体执行(Action)→ 结束(End) 。这一结构不仅保证了资源的有序分配与释放,也为性能指标的精确采集提供了时间边界。

  • 初始化阶段(vuser_init)
    此阶段主要用于建立连接、登录系统、获取会话令牌、加载初始数据等前置准备工作。由于该部分只在 Vuser 启动时执行一次,因此非常适合放置那些不需要重复执行的耗时操作,例如 OAuth 认证、数据库连接初始化等。

  • 主体执行阶段(Action)
    这是 Vuser 执行实际业务逻辑的核心区域,通常包含多个事务(Transaction),如浏览商品、添加购物车、提交订单等。在迭代测试或多循环场景中,Action 可被反复调用,从而模拟持续性的用户活动。

  • 结束阶段(vuser_end)
    用于清理资源,如登出账户、关闭连接、写入日志等。此阶段确保即使测试异常中断,也能尽量完成必要的收尾动作,避免残留会话影响系统状态。

以下是一个典型的 C 语言风格 Vuser 生命周期函数示例:

// 初始化函数
vuser_init()
{
    lr_start_transaction("Login_Init");
    web_add_auto_header("User-Agent", "Mozilla/5.0");
    web_reg_find("Text=Welcome", LAST);

    web_submit_data("login",
        "Action=https://example.com/login",
        "Method=POST",
        ITEMDATA,
        "Name=username", "Value={username}", ENDITEM,
        "Name=password", "Value={password}", ENDITEM,
        LAST);

    lr_end_transaction("Login_Init", LR_AUTO);
    return 0;
}

// 主体执行函数
Action()
{
    lr_start_transaction("Browse_Products");

    web_url("products",
        "URL=https://example.com/products?category={category}",
        "Resource=0",
        "RecContentType=text/html",
        LAST);

    lr_think_time(3); // 模拟用户思考时间

    lr_end_transaction("Browse_Products", LR_AUTO);
    return 0;
}

// 结束函数
vuser_end()
{
    lr_start_transaction("Logout_End");

    web_submit_data("logout",
        "Action=https://example.com/logout",
        "Method=GET",
        LAST);

    lr_end_transaction("Logout_End", LR_AUTO);
    return 0;
}
代码逻辑逐行解读与参数说明
行号 代码片段 解释
6-7 lr_start_transaction(...) 开始记录名为 “Login_Init” 的事务,用于后续统计响应时间。
9 web_add_auto_header 设置全局 HTTP 请求头,确保所有后续请求携带指定 User-Agent。
10 web_reg_find 注册一个检查点,在响应中查找文本“Welcome”,用于验证登录成功。
12-18 web_submit_data 发送 POST 请求至登录接口,使用参数化变量 {username} {password} 提高真实性。
24 lr_think_time(3) 插入 3 秒延迟,模拟用户阅读页面的时间间隔。
30 return 0; 标准返回值,表示函数正常退出。

该结构体现了 LoadRunner 对用户行为的时间维度建模能力。通过合理划分生命周期阶段,可以有效分离一次性设置与重复性操作,提升脚本效率并减少服务器压力误判。

此外,Vuser 在运行时由 Load Generator 实例托管,每个 Generator 可承载数百甚至上千个 Vuser 实例,具体数量取决于脚本复杂度和目标系统的响应速度。如下图所示为 Vuser 生命周期与控制器调度之间的关系:

sequenceDiagram
    participant Controller
    participant LoadGenerator
    participant Vuser

    Controller->>LoadGenerator: 分配 Vuser 数量与启动策略
    LoadGenerator->>Vuser: 触发 vuser_init()
    Vuser-->>LoadGenerator: 完成初始化
    LoadGenerator->>Vuser: 循环调用 Action()
    loop 每次迭代
        Vuser->>Server: 发起 HTTP 请求
        Server-->>Vuser: 返回响应
        Vuser->>Vuser: 记录事务时间 & 检查点
    end
    LoadGenerator->>Vuser: 触发 vuser_end()
    Vuser-->>LoadGenerator: 清理资源
    LoadGenerator-->>Controller: 上报最终结果

该流程图清晰地展示了 Vuser 如何在控制器指令驱动下完成全生命周期的执行过程,同时也揭示了分布式测试中各组件间的协同机制。

2.1.2 基于协议的负载生成原理:HTTP/HTML、C、Java等协议适配逻辑

LoadRunner 支持超过 50 种协议类型,包括常见的 HTTP/HTML、Web Services、SAP GUI、ODBC、JMS 等。不同协议的选择直接影响脚本能捕获的操作粒度和网络交互方式。其中, HTTP/HTML 协议 是最广泛使用的 Web 应用测试模式,适用于基于浏览器的行为录制;而 C-based API 协议 则更适合底层服务接口的压力测试。

不同协议的适用场景对比表
协议类型 适用场景 录制方式 数据解析层级 示例应用
HTTP/HTML 前端 Web 页面交互 浏览器代理录制 HTML DOM + URL 请求 电商平台、OA 系统
Web Services (SOAP/REST) 接口级服务调用 WSDL 导入或手动编写 XML/JSON 报文 支付网关、身份认证
JDBC/ODBC 数据库直连压测 手动编码 SQL SQL 查询与结果集 数据仓库查询性能
Java Vuser Java 应用嵌入式测试 JVM Hook 或 JAR 包注入 字节码层面拦截 自研中间件性能分析
Citrix / RDP 图形化远程桌面应用 屏幕图像识别 + 键鼠事件 图像像素匹配 银行柜面系统

以 HTTP/HTML 协议为例,其工作原理依赖于 HTTP 协议栈的逆向工程 :VuGen 在录制过程中监听浏览器发出的所有 HTTP(S) 请求,自动提取 URL、Headers、Form Data、Cookies 等信息,并将其转换为 web_url() web_submit_data() 等标准函数调用。这种方式无需源码即可还原用户操作路径。

然而,对于富客户端或非标准协议的应用(如 WebSocket、gRPC),则需采用 API 层录制或手动编码 方式。例如,在 Java Vuser 模式下,可通过 Instrumentation 技术注入字节码,捕获方法调用链并生成对应的 jvm_*() 函数序列。

下面展示一段基于 ODBC 协议访问数据库的脚本片段:

SQL()
{
    lr_db_connect("StepName=ConnectToDB",
                  "ConnectionName=MyOracleDB",
                  "ConnectionString=DRIVER={Oracle ODBC Driver};SERVER=prod-db;UID=scott;PWD=tiger;",
                  "ConnectionType=ODBC",
                  LAST);

    lr_db_executeSQLStatement("StepName=QueryUsers",
                              "ConnectionName=MyOracleDB",
                              "SQLStatement=SELECT COUNT(*) FROM users WHERE status='active'",
                              "DatasetName=ActiveCount",
                              LAST);

    lr_db_getValueFromDataset("DatasetName=ActiveCount",
                              "Column=1",
                              "Row=1",
                              "OutParam=total_active",
                              LAST);

    lr_output_message("Active users count: %s", lr_eval_string("{total_active}"));

    lr_db_disconnect("ConnectionName=MyOracleDB", LAST);
    return 0;
}
参数说明与执行逻辑分析
  • lr_db_connect : 建立到 Oracle 数据库的 ODBC 连接,参数包括驱动名称、服务器地址、用户名密码。
  • lr_db_executeSQLStatement : 执行 SQL 查询并将结果存入名为 ActiveCount 的数据集。
  • lr_db_getValueFromDataset : 从结果集中提取第一行第一列的值,并赋给参数 {total_active}
  • lr_eval_string : 解析参数表达式,输出实际数值。
  • lr_db_disconnect : 显式断开连接,防止资源泄露。

此类脚本常用于验证数据库在高并发查询下的锁竞争、索引失效等问题,尤其适合 OLTP 场景的性能基线测试。

综上所述,Vuser 的运行模型本质上是一种 协议驱动的状态机 ,其灵活性来源于对多种通信范式的深度支持。正确选择协议类型并理解其底层工作机制,是确保测试真实性和准确性的前提条件。


2.2 VuGen脚本录制与增强技术

尽管现代性能测试强调自动化与代码化,但脚本录制仍是快速构建基础业务流的有效手段。VuGen 提供了两种主要录制模式: 基于浏览器的录制 基于网络层的录制 ,分别适用于不同架构的应用系统。然而,仅靠录制无法满足真实负载需求,必须结合参数化、关联、逻辑控制等增强技术,才能使脚本具备可重用性与真实性。

2.2.1 录制模式选择:基于浏览器与基于网络层的差异分析

1. 基于浏览器的录制(Browser-Based Recording)

该模式通过启动内置浏览器(如 Chrome 或 IE)并配置代理,实时捕获用户点击、表单提交、AJAX 请求等行为。优点是可视化强、易于调试,适合前端复杂的单页应用(SPA)。但缺点是对 JavaScript 动态生成的内容支持有限,且容易遗漏异步请求。

典型适用场景
- React/Vue/Angular 构建的现代 Web 应用
- 包含大量 AJAX 调用的交互式界面
- 需要完整 DOM 结构还原的测试需求

2. 基于网络层的录制(URL-Based Recording)

此模式直接监控本地网卡流量,截取所有进出的 HTTP(S) 请求包,绕过浏览器渲染层。它能捕捉更细粒度的数据交换,尤其擅长处理 HTTPS 加密流量(需安装证书)。但由于缺乏上下文感知能力,可能产生过多冗余请求(如图标、CSS 文件)。

典型适用场景
- API 优先架构的微服务系统
- 移动 App 后台接口测试(配合 Fiddler 抓包)
- 对性能敏感的核心交易链路压测

以下是两种模式的技术特性对比表:

特性 浏览器录制 网络层录制
请求可见性 仅限浏览器发起的请求 所有 TCP 层 HTTP 流量
JavaScript 支持 弱(无法完全模拟执行) 无(纯抓包)
HTTPS 解密 支持(需信任根证书) 支持(需中间人解密)
冗余请求过滤 自动过滤静态资源 需手动排除无关请求
调试便利性 高(可回放页面) 低(仅显示请求列表)
适用协议 主要是 HTTP/HTML 多协议支持(FTP、SMTP 等)

建议在实际项目中采用 混合录制策略 :先使用网络层录制获取完整请求流,再结合浏览器录制补充 UI 层行为逻辑,最后在 VuGen 中进行合并与精简。

2.2.2 动态数据处理:参数化技术实现用户行为真实模拟

静态脚本在多次迭代中发送相同数据会导致缓存命中偏高、唯一性校验失败等问题,严重影响测试有效性。为此,LoadRunner 提供强大的 参数化(Parameterization)机制 ,允许将常量替换为变量,并从外部数据源动态读取值。

2.2.2.1 参数池配置与数据文件导入策略

参数化可通过三种方式实现:

  1. 内部参数(Internal Parameters) :如 {Date} {Time} {Random} 等系统内置变量。
  2. 数据文件参数(File Parameters) :从 CSV、TXT 文件中逐行读取数据。
  3. 用户定义函数(UDF)或数据库查询 :通过 SQL 查询或其他逻辑生成动态值。

例如,导入一个包含 1000 条用户凭证的 CSV 文件 users.csv

username,password
user_001,pass123
user_002,pass123
user_1000,pass123

在 VuGen 中配置参数属性如下:

属性
Parameter type File
File path ./dat/users.csv
Column delimiter ,
Select next row Sequential
When exhausted Continue with last value

随后在脚本中引用:

web_submit_data("login",
    "Action=https://example.com/login",
    "Method=POST",
    ITEMDATA,
    "Name=username", "Value={username}", ENDITEM,
    "Name=password", "Value={password}", ENDITEM,
    LAST);

此时每次迭代将自动取下一行数据,实现多用户登录模拟。

2.2.2.2 随机化与唯一值分配机制设计

对于需要严格唯一性的字段(如订单号、手机号),应启用 Unique Number 参数类型,并设置取值范围与递增步长:

lr_save_unique_param("order_id", "Min=100000", "Max=999999", "Fail=Error", LAST);

此外,还可结合 lr_next_row() lr_advance_param() 控制数据读取节奏,避免并发冲突。

graph TD
    A[开始录制] --> B{选择录制模式}
    B -->|浏览器| C[捕获UI交互]
    B -->|网络层| D[抓取全量请求]
    C --> E[脚本生成]
    D --> E
    E --> F[参数化替换]
    F --> G[添加检查点]
    G --> H[优化 Think Time/Pacing]
    H --> I[保存为可重用脚本]

该流程图概括了从原始录制到生产级脚本的演进路径,突出了参数化在整个增强过程中的核心地位。


2.3 脚本回放控制与逻辑优化

高质量的性能测试脚本不仅要能运行,更要能真实反映用户行为模式。这要求我们精细调控 Think Time (用户思考时间)与 Pacing (迭代间隔),并在复杂业务流中引入条件判断与循环结构。

2.3.1 Think Time与 pacing 的合理设置以贴近真实用户行为

Think Time 模拟用户在两个操作之间的停顿,单位为秒。默认情况下,VuGen 会保留录制时的实际间隔,但可通过设置策略进行调整:

  • Use recorded think time :保持原样
  • Multiply recorded think time :按比例放大
  • Limit think time :设定最大值,防止过长等待

Pacing 则控制两次 Action 迭代之间的最小时间间隔,常用于模拟固定频率的用户刷新行为。例如,设置 Pacing 为 30 秒意味着无论 Action 执行多久,下一轮都要等到满 30 秒才开始。

lr_set_transaction("Browse", LR_BUSINESS_FLOW);
lr_start_transaction("Browse");

// 模拟浏览3个页面
for (int i = 1; i <= 3; i++) {
    web_url(lr_eval_string("page_{i}"),
            "URL=https://example.com/item?id={item_id_{i}}", LAST);
    lr_think_time(2 + rand() % 3); // 2~4秒随机思考时间
}

lr_end_transaction("Browse", LR_AUTO);

// 设置下一次迭代至少等待15秒
lr_pacing_delay(15);

上述代码实现了带有随机化 Think Time 的浏览行为,并通过 lr_pacing_delay() 强制控制整体节奏,避免瞬时高峰。

2.3.2 条件判断与循环结构在复杂业务流中的应用

许多业务具有分支逻辑,如“余额充足则支付,否则提示充值”。此时需使用标准 C 控制语句:

// 获取账户余额(假设已存储在参数 {balance} 中)
double bal = atof(lr_eval_string("{balance}"));

if (bal >= 100.0) {
    lr_start_transaction("Pay_Order");
    web_submit_data("pay",
        "Action=https://example.com/pay",
        "Method=POST",
        ITEMDATA,
        "Name=amount", "Value=100.00", ENDITEM, LAST);
    lr_end_transaction("Pay_Order", LR_PASS);
} else {
    lr_output_message("Insufficient balance: %.2f", bal);
    lr_error_message("Payment skipped due to low balance.");
}

循环结构可用于批量操作:

for (int i = 1; i <= atoi(lr_eval_string("{num_items}")); i++) {
    web_url(lr_eval_string("add_item_{i}"),
            "URL=https://example.com/cart/add?pid={product_{i}}", LAST);
    lr_think_time(1);
}

这些编程结构极大增强了脚本的表现力,使其能够覆盖真实的用户决策路径。

综上,VuGen 不只是一个录制工具,更是功能完备的性能脚本 IDE。只有充分掌握其生命周期管理、协议适配、参数化与逻辑控制能力,才能构建出既能高效运行又能真实反映用户行为的高质量测试资产。

3. 控制器场景设计与负载执行策略

在现代企业级应用系统中,性能表现不仅关乎用户体验,更直接影响业务连续性与系统可用性。LoadRunner的控制器(Controller)模块作为性能测试的核心调度中枢,承担着从虚拟用户组织、负载模型构建到实际压力施加的全过程管理职责。本章将深入剖析控制器在复杂业务环境下的场景设计逻辑与负载执行机制,重点探讨如何基于真实业务流量特征建立科学合理的负载模型,并通过精细化调度策略实现对系统极限能力的精准探测。

3.1 场景规划与负载模型构建

有效的性能测试始于精确的场景建模。一个成熟的负载测试场景不应是简单地“启动若干Vuser并发访问”,而应反映生产环境中真实的用户行为分布、操作频率和请求组合。因此,场景规划阶段需综合考虑业务类型、用户角色、操作路径及时间维度等多个因素,形成可量化、可复现的负载模型。

3.1.1 基于业务混合比例的多Vuser组配置方法

在典型的Web或移动端应用中,不同类型的用户会执行差异化的业务流程。例如,在电商平台中可能存在“浏览商品”、“添加购物车”、“提交订单”、“支付结算”等多种用户行为流。这些行为在真实环境中并非均匀分布,而是遵循一定的业务权重比例。若忽略该比例直接使用单一脚本进行压测,将导致结果失真,无法准确评估系统的整体承载能力。

为解决这一问题,LoadRunner提供了 多Vuser组(Multiple Vuser Groups) 的机制,允许测试人员为每种业务流创建独立的虚拟用户组,并按预设比例分配其数量。这种配置方式能够更真实地模拟生产环境中的用户行为构成。

多Vuser组配置逻辑解析

假设某电商系统日均活跃用户为50,000人,其中各业务模块的访问占比统计如下:

业务类型 访问占比 模拟并发数(取1%在线)
商品浏览 60% 300
购物车操作 20% 100
下单流程 15% 75
支付交易 5% 25

根据上述数据,在Controller中可创建四个Vuser组,分别对应四类业务脚本,并设置初始并发数为: Browse=300 , Cart=100 , Order=75 , Payment=25

// 示例:VuGen中定义不同业务流程的Action段落结构
Action()
{
    lr_start_transaction("Browse_Product");

    web_url("product_list",
        "URL=https://shop.example.com/api/products?page=1",
        "Resource=0",
        "RecContentType=application/json",
        LAST);

    lr_end_transaction("Browse_Product", LR_AUTO);

    return 0;
}

Action_Cart()
{
    lr_start_transaction("Add_To_Cart");

    web_submit_data("add_item",
        "Action=https://shop.example.com/api/cart/add",
        "Method=POST",
        "RecContentType=application/json",
        ITEMDATA,
        "Name=productId", "Value=1001", ENDITEM,
        "Name=quantity", "Value=1", ENDITEM,
        LAST);

    lr_end_transaction("Add_To_Cart", LR_AUTO);

    return 0;
}

代码逻辑逐行解读
- lr_start_transaction() :标记事务开始,用于后续性能指标采集。
- web_url() / web_submit_data() :发送HTTP GET/POST请求,模拟具体业务动作。
- LAST :表示参数列表结束,属于LoadRunner脚本语法规范。
- lr_end_transaction() :结束事务并自动记录响应时间,第二个参数 LR_AUTO 表示根据响应内容自动判断成功或失败。

在Controller界面中,通过“Scenario → Enable Percentage Mode”启用百分比模式后,可以直观设定每个Vuser组所占的比例。系统会自动根据总Vuser数按比例分配各组实例,确保负载分布符合预期。

此外,还可结合Think Time随机化(如Uniform或Normal分布)以及Pacing间隔控制,进一步增强行为真实性。例如,浏览类操作通常节奏较快但停留时间短,而支付类操作则涉及多次跳转和确认,应设置较长的思考时间。

负载模型优化建议
  • 避免“峰值叠加”陷阱 :不要将所有高耗时事务集中在同一时间段运行,否则可能人为制造瓶颈。
  • 引入背景流量 :可在主业务流之外增加低频度的健康检查、心跳上报等后台任务,提升网络层仿真精度。
  • 动态调整组权重 :支持在运行期间通过API或GUI手动修改Vuser组比例,以测试突发流量切换场景下的系统适应性。
graph TD
    A[业务流量分析] --> B{是否支持多角色?}
    B -->|是| C[划分Vuser组]
    B -->|否| D[单组全量压测]
    C --> E[确定各组比例]
    E --> F[导入对应VuGen脚本]
    F --> G[设置Ramp-up策略]
    G --> H[启动场景执行]
    H --> I[监控实时TPS与错误率]
    I --> J{是否达到稳态?}
    J -->|否| K[调整并发或参数]
    J -->|是| L[进入稳定期采集数据]

流程图说明 :展示了从原始业务分析到最终稳定压测的完整路径。强调了多Vuser组配置在整个流程中的关键作用,尤其适用于异构业务混合型系统。

3.1.2 Ramp-up、Ramp-down及稳定阶段的时间设定原则

负载的“渐进式”施加对于识别系统拐点至关重要。若一次性启动全部Vuser,极易造成瞬时拥塞,掩盖真正的性能瓶颈;反之,过于缓慢的增长又可能导致测试周期过长,影响效率。因此,合理设置Ramp-up、稳定期与Ramp-down三个阶段的时间参数,是构建有效负载模型的关键环节。

Ramp-up 阶段设计准则

Ramp-up是指从0开始逐步增加并发用户数直至目标值的过程。推荐采用线性增长模式,其公式为:

N(t) = N_{max} \times \frac{t}{T_{rampup}}

其中 $N(t)$ 表示t时刻的并发数,$N_{max}$为目标最大并发,$T_{rampup}$为总上升时间。

一般建议:
- 对于中小规模系统(<1000 Vusers),Ramp-up时间控制在 3~5分钟
- 对大型分布式系统(>5000 Vusers),可延长至 10~15分钟 ,以防中间件连接池瞬间耗尽。

同时应注意Load Generator的负载能力上限。若单台LG仅能支撑800 Vusers,则需分摊部署,避免资源争抢。

稳定阶段持续时间要求

稳定期是采集核心性能指标的主要窗口,必须保证系统已进入稳态运行。判断标准包括:
- TPS波动范围小于±5%
- 平均响应时间趋于收敛
- 错误率维持低位且无新增异常

建议稳定期持续 至少15分钟 ,以便捕获偶发GC、缓存失效等周期性事件的影响。

Ramp-down 策略选择

Ramp-down即逐步减少Vuser数量至零。虽然该阶段不用于主要数据分析,但仍有必要设置适当时长(推荐 2~3分钟 ),以观察系统在压力释放过程中的恢复行为,如连接关闭延迟、资源释放速度等。

以下表格总结了典型场景的时间配置参考:

场景类型 总Vusers Ramp-up(min) 稳定期(min) Ramp-down(min) 说明
功能回归压测 200 2 10 1 快速验证基本可用性
容量评估测试 2000 10 30 3 全面采集性能拐点
峰值压力冲击测试 5000 5 15 2 检验瞬时抗压能力
长时间稳定性测试 1000 5 120 5 观察内存泄漏趋势

参数说明
- Ramp-up过短易引发TCP连接风暴;
- 稳定期不足会导致平均值被初期波动拉高;
- Ramp-down过快可能遗漏连接未释放问题。

此外,Controller支持“Schedule by Real Users”模式,允许按每秒新增用户数(Users per second)来定义增长速率,更适合模拟自然流量爬升过程。

3.2 实际业务场景模拟与负载调度

完成基础负载模型构建后,下一步是通过高级调度功能实现对真实业务场景的精细还原。LoadRunner提供多种机制来强化并发控制与行为同步,其中最具代表性的便是集合点(Rendezvous Point)。

3.2.1 手动场景与目标导向场景的适用场景对比

LoadRunner Controller支持两种主要的场景模式: Manual Scenario Goal-Oriented Scenario ,二者在用途、灵活性与自动化程度上存在显著差异。

特性 手动场景(Manual) 目标导向场景(Goal-Based)
控制粒度 用户数、迭代次数 可设定TPS、响应时间、吞吐量等KPI
自动调节 不支持 支持动态增减Vuser以逼近目标
适用阶段 探索性测试、调优验证 SLA合规性验证、容量规划
配置复杂度 较低 较高,需明确定义成功条件
结果可预测性 中等(受算法收敛影响)
典型应用场景 内部性能摸底 客户验收、上线前合规测试
手动场景的应用实践

手动场景适用于需要完全掌控测试流程的场合。例如,在排查数据库锁竞争问题时,测试人员希望精确控制并发线程数,并在特定时刻注入突增流量以触发死锁条件。此时可通过脚本中的 lr_rendezvous("DB_Lock_Test") 插入集合点,并配合固定数量的Vuser进行精准打击。

Action()
{
    lr_start_transaction("Withdraw_Funds");

    lr_rendezvous("High_Concurrency_Point"); // 强制在此处等待其他Vuser汇合

    web_service_call( "StepName=transferMoney",
        "SOAPMethod=BankService.Account.withdraw",
        "ResponseParam=response",
        "Service=http://bank.example.com/ws/BankService?wsdl",
        "ExpectResponse=YES",
        "Snapshot=t1.inf",
        BEGIN_ARGUMENTS,
        "amount=500",
        "accountId={AccountId}",
        END_ARGUMENTS,
        BEGIN_RESULT,
        "resultStatus={Status}",
        END_RESULT,
        LAST);

    if (atoi(lr_eval_string("{Status}")) != 200)
    {
        lr_abort(); // 若返回非成功状态码则终止当前Vuser
    }

    lr_end_transaction("Withdraw_Funds", LR_AUTO);

    return 0;
}

代码解释
- lr_rendezvous() :设置集合点名称,所有属于同一场景的Vuser运行至此将暂停,直到满足指定策略(如全部到达或超时)才继续执行。
- web_service_call() :调用SOAP接口,常用于银行、保险等传统企业系统集成测试。
- lr_abort() :主动中断当前Vuser执行,可用于模拟失败用户退出行为。

目标导向场景的自动化优势

相比之下,目标导向场景更适合SLA驱动的正式测试。例如,客户要求“95%的交易响应时间不超过2秒”,此时可在Controller中新建目标场景,选择“Transaction Response Time”为目标类型,输入阈值2000ms,并指定关联事务名。

系统将自动执行以下流程:
1. 初始以少量Vuser启动;
2. 监控实时响应时间;
3. 若低于目标,则逐步增加负载;
4. 当接近阈值时停止增长;
5. 输出最终可持续的最大负载量。

此模式极大减少了人工试错成本,特别适合用于发布前的性能达标测试。

3.2.2 集合点(Rendezvous)设置对并发压力的影响分析

集合点是LoadRunner中最强大的并发控制工具之一,它允许多个Vuser在同一逻辑位置“汇合”,从而实现瞬间高并发冲击,用于检测系统在极端并发下的表现。

集合点工作原理

当Vuser执行到 lr_rendezvous("name") 语句时,会被挂起并加入等待队列。只有当满足以下任一条件时才会释放:
- 所有参与该集合点的Vuser均已到达;
- 达到预设的超时时间(默认30秒);
- 管理员手动释放。

该机制可有效打破“伪并发”现象——即由于网络延迟或客户端处理速度不同,导致看似并发的操作实际上呈串行执行。

设置策略与风险提示

尽管集合点威力强大,但滥用可能导致误导性结果。常见误区包括:
- 在高频事务中设置集合点,造成不必要的阻塞;
- 忽略超时设置,导致部分Vuser永久卡住;
- 未结合Think Time使用,产生非自然的“脉冲式”负载。

推荐的最佳实践如下:
- 仅在关键业务节点(如秒杀下单、抽奖开奖)设置集合点;
- 设置合理超时(建议60秒以内);
- 结合日志输出跟踪汇合进度。

sequenceDiagram
    participant Vuser1
    participant Vuser2
    participant Vuser3
    participant Controller

    Vuser1->>Controller: 到达集合点 RZ_Login
    Vuser2->>Controller: 到达集合点 RZ_Login
    Vuser3->>Controller: 到达集合点 RZ_Login
    Controller->>All: 释放所有Vuser
    Vuser1->>App: 发送登录请求
    Vuser2->>App: 发送登录请求
    Vuser3->>App: 发送登录请求

序列图说明 :展示三个Vuser在Controller协调下实现同步并发的过程。体现了集合点在制造真实并发压力方面的价值。

3.3 分布式负载生成与运行时服务器协同

面对大规模并发需求,单台Load Generator(LG)往往难以胜任。此时必须借助分布式架构,将负载分散至多台机器,以突破硬件限制。

3.3.1 Load Generator部署与连接测试技巧

Load Generator是负责实际执行Vuser脚本的代理进程,可在Windows或Linux平台上安装。要实现高效协同,需注意以下几点:

部署前准备清单
检查项 说明
网络连通性 确保LG能与Controller直连,端口54348开放
时间同步 使用NTP服务保持各节点时间一致,防止日志错乱
脚本依赖文件完整性 如参数文件、证书、DLL等需提前复制到位
杀毒软件/防火墙干扰排除 关闭实时扫描,防止脚本执行卡顿
资源预留 建议每800 Vusers保留1核CPU+2GB内存
连接测试步骤
  1. 在Controller中点击“Generators”标签页;
  2. 添加新LG主机IP或域名;
  3. 输入远程登录凭据(Windows需启用Remote Registry服务);
  4. 点击“Connect”发起握手;
  5. 查看状态是否显示“Ready”。

若连接失败,可通过以下命令诊断:

telnet controller_ip 54348

若无法建立TCP连接,则需检查防火墙规则或SELinux策略。

分布式负载分配示例

假设有3台LG,每台最大支持1000 Vusers,总目标为2500并发。可在Controller中按如下比例分配:

LG编号 IP地址 分配Vusers 脚本类型
LG-01 192.168.1.101 1000 浏览+购物车
LG-02 192.168.1.102 1000 下单+支付
LG-03 192.168.1.103 500 后台同步任务

这样既能均衡负载,又能隔离不同类型的压力源,便于后期问题定位。

3.3.2 网络延迟仿真与带宽限制配置以提升测试真实性

实验室环境通常具备理想化的低延迟、高带宽网络,这与真实用户的广域网接入条件相差甚远。为此,LoadRunner内置了 Network Emulation 功能,可在LG层面模拟不同等级的网络质量。

配置路径与参数含义

在Controller的“Scenario Schedule”中,选择“Enable Network Speed Simulation”,然后选择预设带宽模板:

模板名称 下行带宽 上行带宽 延迟(ms) 适用场景
LAN 100 Mbps 100 Mbps 1 内网系统测试
Cable/DSL 5 Mbps 512 Kbps 30 家庭宽带用户
3G Mobile 1.5 Mbps 384 Kbps 100 移动端弱网环境
4G LTE 15 Mbps 5 Mbps 50 主流移动网络

也可自定义参数,精确控制抖动(jitter)、丢包率(packet loss)等高级选项。

实际效果对比

启用网络延迟仿真后,可观测到:
- HTTP首包时间显著增加;
- 大文件上传/下载吞吐量下降;
- AJAX轮询类接口可能出现超时累积;
- 前端渲染延迟感知明显。

这对于前端性能优化、CDN选型、静态资源压缩策略制定具有重要指导意义。

综上所述,控制器不仅是负载的“开关”,更是整个性能测试工程的大脑。唯有深入理解其调度逻辑与协同机制,方能在复杂系统中实施高质量的压力验证。

4. 性能监控体系构建与瓶颈诊断方法

在高并发系统日益普及的今天,仅依靠负载生成已无法满足对系统稳定性和可扩展性的全面评估。真正的性能测试价值,体现在对运行过程中各类指标的精准采集、实时监控以及深层次的问题定位能力上。LoadRunner 提供了一套完整的性能监控体系,覆盖从应用层事务行为到底层服务器资源消耗的全链路观测维度。本章将深入探讨如何科学配置多层级监控项,结合断言机制保障结果有效性,并通过系统化的分析路径识别潜在性能瓶颈。整个过程不仅依赖工具功能本身,更需要测试工程师具备清晰的技术逻辑和跨层关联分析能力。

4.1 多维度性能指标采集与监控配置

现代分布式系统的复杂性决定了单一指标难以反映整体性能状况。有效的性能监控必须建立在多层次、多来源的数据采集基础之上。LoadRunner 支持对接多种监控源,包括本地或远程主机的操作系统级指标、数据库实例状态、Web 服务器(如 Apache、IIS)、中间件(如 WebLogic、Tomcat)乃至云平台(如 AWS CloudWatch)。这些数据共同构成了一个立体化的性能视图,为后续的瓶颈分析提供坚实支撑。

4.1.1 应用层指标:事务响应时间、每秒事务数(TPS)、错误率

应用层指标是用户感知最直接的性能体现,也是衡量业务可用性的核心依据。其中最具代表性的三个指标为:

  • 事务响应时间 :指完成一次完整业务操作所耗费的时间,通常包含网络传输、服务器处理及数据库交互等环节。
  • 每秒事务数(Transactions Per Second, TPS) :反映系统单位时间内能够成功处理的业务请求数量,是衡量吞吐能力的关键参数。
  • 错误率 :即失败事务占总事务的比例,用于判断系统在压力下的稳定性。

在 LoadRunner Controller 中,可通过“Runtime Settings”中的“Enable Monitors”选项开启应用层监控。以下代码片段展示了如何在脚本中定义事务边界并记录关键指标:

// 开始一个名为"Login_Process"的事务
lr_start_transaction("Login_Process");

// 模拟登录请求
web_submit_data("login",
    "Action=http://example.com/auth/login",
    "Method=POST",
    ITEMDATA,
    "Name=username", "Value={username}", ENDITEM,
    "Name=password", "Value={password}", ENDITEM,
    LAST);

// 检查响应是否包含“Welcome”
if (strstr(lr_eval_string("{LAST_RESPONSE}"), "Welcome") != NULL) {
    lr_end_transaction("Login_Process", LR_PASS);
} else {
    lr_end_transaction("Login_Process", LR_FAIL);
}

代码逻辑逐行解读

  • lr_start_transaction("Login_Process"); :标记事务开始,名称为 “Login_Process”,该名称将在 Analysis 报告中显示。
  • web_submit_data() :发送 POST 请求模拟用户登录动作,使用参数化变量 {username} {password} 实现多用户行为模拟。
  • lr_eval_string("{LAST_RESPONSE}") :获取上一个请求返回的内容,便于做内容校验。
  • strstr(...) :C 标准库函数,用于查找子字符串是否存在;若找到“Welcome”则认为登录成功。
  • lr_end_transaction(...) :根据条件结束事务,并传入 LR_PASS 或 LR_FAIL 来标记成功或失败。

此段代码实现了典型的事务封装与结果判定流程,确保收集到准确的响应时间和成功率数据。执行后,在 Analyzer 中可查看如下趋势图表:

graph TD
    A[虚拟用户启动] --> B{是否到达集合点?}
    B -- 是 --> C[并发执行登录事务]
    C --> D[采集响应时间]
    D --> E[计算TPS]
    E --> F[统计错误率]
    F --> G[输出至Analysis报告]

流程图说明 :该 mermaid 图描述了从 Vuser 启动到最终生成性能数据的全过程。重点在于事务被明确划分,并通过条件判断决定事务状态,从而影响 TPS 与错误率的统计精度。

此外,下表列出了常见应用场景中推荐关注的应用层指标阈值参考:

应用类型 平均响应时间(ms) 建议 TPS 下限 错误率上限
电商平台首页 ≤ 800 ≥ 200 ≤ 0.5%
银行转账交易 ≤ 1500 ≥ 50 ≤ 0.1%
社交媒体动态刷新 ≤ 600 ≥ 300 ≤ 1%
后台管理查询 ≤ 2000 ≥ 20 ≤ 2%

参数说明 :以上数值基于行业通用标准设定,实际项目需结合 SLA 协议进行调整。例如金融类系统对错误率容忍度极低,而内容型网站可能更注重响应速度而非绝对零失败。

值得注意的是,响应时间并非越短越好,还需结合 Think Time(思考时间)设置以模拟真实用户行为。若忽略这一点,可能导致测试流量远高于生产环境,造成误判。

4.1.2 系统层指标:CPU使用率、内存占用、磁盘I/O与网络吞吐量

当应用层出现性能退化时,下一步应转向系统资源层面排查根本原因。LoadRunner 允许通过添加“Windows Resources”、“UNIX/Linux Resources”或“Database Monitors”来采集目标服务器的各项硬件指标。

监控配置步骤示例(以 Windows 主机为例):
  1. 在 Controller 的“Scenario”菜单中选择“Add Measurements”;
  2. 选择“Windows Resources”;
  3. 输入目标服务器 IP 地址及具有管理员权限的账户凭据;
  4. 勾选需监控的计数器,如:
    - \Processor(_Total)\% Processor Time
    - \Memory\Available MBytes
    - \PhysicalDisk(_Total)\Avg. Disk Queue Length
    - \Network Interface(*)\Bytes Total/sec

成功连接后,LoadRunner 将周期性轮询 WMI(Windows Management Instrumentation)接口获取实时数据。

以下是一个典型的资源监控数据采样表示例:

时间戳 CPU 使用率 (%) 可用内存 (MB) 磁盘队列长度 网络吞吐量 (KB/s)
10:00 35 2048 1.2 450
10:05 68 1200 2.7 920
10:10 89 600 6.5 1400
10:15 96 256 10.3 1650
10:20 75 800 4.1 1100

表格分析 :随着负载上升,CPU 使用率接近饱和(>90%),同时可用内存急剧下降,磁盘队列显著增长,表明 I/O 成为瓶颈。此时即使 TPS 未达峰值,也应怀疑存在锁表或慢查询问题。

为增强监控灵活性,也可通过自定义脚本方式注入 SNMP 查询逻辑。例如使用 lr_exec_query 调用外部命令获取 Linux 系统负载:

// 执行 shell 命令获取 top 信息
lr_execute_shell(
    "command=ssh user@192.168.1.100 'top -b -n 1 | grep \"Cpu(s)\"'",
    "output_param=top_cpu_output",
    LAST
);

// 提取 CPU idle 百分比
double cpu_idle = atof(lr_param_sprintf("str_extract(%s, \"\\d+\\.\\d+ id\", 0)", "{top_cpu_output}"));
double cpu_usage = 100.0 - cpu_idle;

// 写入用户自定义监控点
lr_user_data_point("Custom_CPU_Usage", cpu_usage);

代码解释与参数说明

  • lr_execute_shell() :执行远程 shell 命令,适用于无法直接添加操作系统监控的情况。
  • "output_param" :指定将命令输出保存到哪个参数名中,便于后续解析。
  • atof() + 正则提取:从文本中解析浮点数值,此处假设返回格式为 97.2 id 表示空闲占比。
  • lr_user_data_point() :将计算出的 CPU 使用率作为自定义指标上传至 Controller,可在 Analysis 中绘制曲线图。

该技术特别适用于容器化部署环境(如 Kubernetes Pod 内部资源隔离场景),弥补传统 WMI/SSH 监控无法深入容器内部的缺陷。

pie
    title 系统资源瓶颈分布(基于历史案例统计)
    “CPU 瓶颈” : 35
    “内存不足” : 20
    “磁盘 I/O 过载” : 25
    “网络带宽限制” : 15
    “其他(锁竞争、GC频繁)” : 5

饼图说明 :通过对多个真实项目的归因分析发现,超过 80% 的性能问题可归结为上述四种主要资源瓶颈。因此,在设计监控方案时应优先覆盖这四类指标,并设置告警阈值实现早期预警。

综上所述,系统层监控不仅是性能测试的“黑盒补充”,更是实现根因定位不可或缺的一环。只有将应用表现与底层资源联动分析,才能避免“治标不治本”的优化误区。

4.2 断言与检查点在结果验证中的实践应用

性能测试不仅仅是压测和看数字,更重要的是验证系统在高压下仍能正确处理业务逻辑。这就需要引入断言(Assertions)机制,确保响应内容符合预期。LoadRunner 提供了多种检查点技术,可用于验证 HTML 页面内容、JSON 响应字段、HTTP 状态码等关键要素。

4.2.1 文本/正则表达式检查点确保响应内容正确性

在 VuGen 脚本中,可通过 web_reg_find() 函数设置文本检查点,检测响应流中是否包含特定字符串。例如,在登录成功后期望页面返回“欢迎您,张三”:

// 设置响应中必须包含欢迎语句
web_reg_find(
    "Text=欢迎您,{real_name}",
    "SaveCount=welcome_count",
    LAST
);

// 发起登录请求
web_submit_data("user_login",
    "Action=https://app.example.com/login",
    "Method=POST",
    ITEMDATA,
    "Name=uid", "Value={username}", ENDITEM,
    "Name=pwd", "Value={password}", ENDITEM,
    LAST);

参数说明

  • "Text=..." :指定要搜索的文本内容,支持参数化变量 {real_name}
  • "SaveCount=..." :将匹配次数存入指定参数,若为 0 则说明未找到。
  • 若未找到匹配内容,VuGen 回放会自动标记为失败,无需手动调用 lr_fail_if_not .

进一步地,对于结构化数据(如 JSON API),可采用正则表达式进行更精细的断言。例如验证返回 JSON 中 status 字段为 "success"

// 使用正则表达式检查 JSON 响应状态
web_reg_find(
    "Text/Body={\"status\":\"success\"",
    "SaveCount=status_ok",
    LAST
);

或者结合 lr_xml_search 对 XML 响应做 XPath 匹配:

// 查找订单ID节点是否存在
lr_xml_search(
    "Xml={response_body}",
    "Query=/response/order/id",
    "ValueParam=order_id_found",
    LAST
);

此类检查点极大提升了脚本的健壮性,防止因前端缓存、CDN 返回旧页面而导致误判性能达标。

4.2.2 自定义日志断言辅助调试与异常追踪

除了内置检查点外,合理使用日志输出也能有效提升问题排查效率。LoadRunner 提供 lr_output_message() lr_error_message() 等函数输出上下文信息。

// 输出当前用户名和响应码
lr_output_message("正在测试用户: %s, Response Code: %s", 
                  lr_eval_string("{username}"), 
                  lr_eval_string("{RESPONSE_CODE}"));

// 若状态码非200,则记录错误并中断事务
if (atoi(lr_eval_string("{RESPONSE_CODE}")) != 200) {
    lr_error_message("HTTP错误:%s", lr_eval_string("{RESPONSE_CODE}"));
    lr_abort(); // 终止当前Vuser
}

逻辑分析

  • lr_output_message() :普通信息输出,常用于跟踪执行流程。
  • lr_error_message() :标记为错误级别,会在 Controller 日志中标红提示。
  • lr_abort() :强制终止当前 Vuser 执行,避免无效请求继续占用资源。

建议在关键事务前后插入日志断言,特别是在涉及支付、审批等敏感业务流程中,确保每一步都有迹可循。

sequenceDiagram
    participant Vuser
    participant Server
    participant Checkpoint
    Vuser->>Server: 发送登录请求
    Server-->>Vuser: 返回HTML页面
    Vuser->>Checkpoint: 执行web_reg_find检查
    alt 检查通过
        Checkpoint-->>Vuser: 继续执行下一步
    else 检查失败
        Checkpoint->>Vuser: 触发lr_error_message
        Vuser->>Controller: 记录失败事务
    end

流程图说明 :该序列图展示了检查点介入请求响应流程的方式。它发生在后台回调阶段(reg_find 为注册式函数),不影响主请求流程,但能及时捕获异常内容。

综合来看,断言机制是连接“性能”与“功能正确性”的桥梁。没有可靠的验证手段,再高的 TPS 也可能掩盖严重的业务逻辑缺陷。

4.3 性能瓶颈初步定位路径

面对复杂的性能退化现象,必须有一套系统化的诊断路径,避免陷入“盲调参数”的困境。LoadRunner 提供了丰富的数据分析工具,但真正的挑战在于如何组织思路,逐步缩小问题范围。

4.3.1 响应时间分解:网络延迟 vs 服务器处理耗时

响应时间通常由多个部分构成:

T_{total} = T_{network_out} + T_{server_processing} + T_{network_in}

LoadRunner 默认提供“Time to First Buffer”和“Time to Last Buffer”两个细分指标,可用于估算各阶段耗时:

指标名称 含义 用途
Time to First Buffer 客户端发出请求到收到第一个字节的时间 反映网络延迟与服务器排队时间
Time to Last Buffer 收到最后一个数据包的时间 包含传输大数据体所需时间

Time to First Buffer 占比过高,说明服务器响应慢或网络拥塞;若两者差距大,则可能是返回内容过大导致下载缓慢。

可通过以下脚本增强时间切片分析能力:

double t1, t2;

t1 = lr_get_transaction_duration(NULL); // 获取事务已耗时间

web_url("large_report",
    "URL=https://report.example.com/export?format=pdf",
    LAST);

t2 = lr_get_transaction_duration(NULL);

lr_output_message("网络传输耗时: %.2f 秒", t2 - t1);

参数说明

  • lr_get_transaction_duration(NULL) :返回当前事务累计耗时(单位:秒)。
  • 两次调用差值即为该请求的实际耗时,可用于对比不同组件的时间占比。

实践中建议绘制“响应时间分解堆叠图”,直观展示各阶段贡献比例。

4.3.2 资源瓶颈识别:通过关联分析发现数据库或中间件瓶颈

当发现响应时间升高时,应立即查看对应时间段内的资源使用情况。典型做法是将 TPS 曲线与 CPU、内存、数据库连接数叠加在同一坐标轴中观察相关性。

例如,若出现以下模式:

  • TPS 上升 → CPU 使用率平稳 → 响应时间陡增 → 数据库连接池耗尽

则可初步判断瓶颈位于数据库层,可能原因为:

  • 缺少索引导致全表扫描
  • 长事务阻塞写操作
  • 连接池配置过小

此时可通过 LoadRunner 添加 Oracle 或 MySQL 监控项,查看“Active Sessions”、“Buffer Hit Ratio”、“Lock Waits”等关键指标。

-- 示例:查询MySQL当前活跃连接数
SHOW STATUS LIKE 'Threads_connected';

并将结果纳入趋势分析。一旦确认数据库为瓶颈,即可协同 DBA 进行 SQL 优化或扩容处理。

总之,性能瓶颈诊断是一场跨层级、跨团队的协作战役。唯有构建起涵盖应用、系统、中间件、数据库的全方位监控体系,并辅以严谨的断言与时间分解方法,方能在海量数据中抽丝剥茧,锁定真凶。

5. 分析器深度解读与CI/CD集成优化实践

5.1 Analyzer中性能数据可视化与趋势分析

LoadRunner Analysis模块作为性能测试结果的“大脑”,承担着从海量原始数据中提炼关键洞察的核心任务。其强大的图形化能力允许测试工程师对系统在不同负载阶段的行为进行精准刻画。

以一次典型的电商大促压测为例,执行完成后将 .lrr 结果文件导入Analyzer,系统会自动解析并生成多个默认图表。其中最关键的三类图表包括:

  • Average Transaction Response Time (Over Time) :展示各事务随时间变化的平均响应时长。
  • Transactions per Second (TPS) :反映系统吞吐能力的变化趋势。
  • Windows Resources – CPU & Memory Usage :叠加显示被监控服务器资源使用情况。
graph TD
    A[原始Vuser日志] --> B{Analyzer解析}
    B --> C[事务响应时间序列]
    B --> D[吞吐量时间序列]
    B --> E[资源监控指标]
    C --> F[绘制响应时间曲线]
    D --> G[绘制TPS图]
    E --> H[资源利用率叠加图]
    F --> I[识别性能拐点]
    G --> I
    H --> I
    I --> J[输出瓶颈假设]

通过“合并图”功能可将多个维度的数据叠加在同一坐标系中。例如,将“登录事务响应时间”与“应用服务器CPU使用率”叠加后发现:当CPU超过75%阈值时,响应时间呈指数级上升——这表明可能存在线程阻塞或JVM GC频繁问题。

此外,Analyzer提供“过滤器”机制用于定位异常时段。可通过以下步骤追溯事务失败根因:

  1. 在Results菜单中选择”Errors” → “Error Statistics”
  2. 查看错误类型分布(如HTTP 500、Socket连接超时等)
  3. 使用“Drill Down to Errors”功能跳转至具体出错的Vuser和时间戳
  4. 结合扩展日志查看该时刻请求参数与响应内容

例如,在某次银行转账场景测试中,发现约有2%的事务返回“Insufficient Balance”错误。通过筛选这些错误记录并与参数化数据关联分析,最终确认是由于余额字段未正确绑定导致逻辑误判。

Analyzer还支持“场景比较”功能,可用于版本迭代间的性能回归评估。选择两个相近负载条件下的测试结果,系统将自动生成差异报告,突出显示TPS下降超过10%或响应时间增长显著的事务。

5.2 自动化报告生成与结果交付标准化

为提升测试成果的可交付性,Analyzer提供了灵活的报告模板定制机制。通过“Report Templates”功能,可预设面向不同干系人的输出格式:

干系人角色 关注重点 推荐图表
开发人员 错误详情、代码瓶颈 错误分布图、函数级调用栈
运维团队 资源瓶颈、容量预警 CPU/Memory/IOPS趋势图
项目经理 整体达标率、SLA符合度 摘要仪表盘、达标状态表

创建自定义模板流程如下:

  1. 打开“Report” → “Template Management”
  2. 复制内置模板“Standard Template”并重命名为“DevOps_Perf_Report_v2”
  3. 删除冗余图表(如Web Page Breakdown)
  4. 添加“Service Level Agreement (SLA)”表格
  5. 插入公司LOGO与保密声明页眉页脚
  6. 保存为共享模板供团队复用

生成报告后,可导出为多种格式:
- .pdf :用于正式评审会议
- .xls :便于财务部门做成本核算
- .mht :包含完整交互式图表的单文件归档

更进一步地,可通过VBA脚本实现与Power BI的自动化对接:

Sub ExportToPowerBI()
    Dim xlApp As Object
    Set xlApp = CreateObject("Excel.Application")
    xlApp.Visible = False
    Dim wb As Object
    Set wb = xlApp.Workbooks.Open("C:\LR_Results\Daily_LoadTest.xls")
    ' 提取关键指标工作表
    wb.Sheets("Summary").Copy
    ActiveWorkbook.SaveAs "C:\PowerBI\DataLake\PerfMetrics_" & Format(Now(), "YYYYMMDD") & ".csv"
    wb.Close False
    xlApp.Quit
End Sub

该脚本每日凌晨由Windows Task Scheduler触发,将最新测试结果同步至企业数据湖,供Power BI实时仪表板消费。

此外,Analyzer支持命令行模式运行,便于集成到自动化流水线中:

analyzer -testname "Nightly_Stress_Test" -resultpath "D:\LR\Results\20241005" -reporttemplate "DevOps_Template" -output "D:\Reports\Oct05.pdf"

此命令可在无GUI环境下批量生成标准化报告,极大提升了持续性能验证效率。

5.3 LoadRunner与DevOps流水线集成

在现代CI/CD实践中,性能测试不应是发布前的“最后一道关卡”,而应作为质量门禁嵌入每日构建流程。LoadRunner Professional与Enterprise版本均支持与Jenkins等主流工具链的深度集成。

实现自动化触发的关键在于 mdrv.exe lrapi 命令行接口。以下是Jenkins Pipeline中的典型配置片段:

pipeline {
    agent any
    stages {
        stage('Performance Test') {
            steps {
                script {
                    bat '''
                    "C:\\Program Files\\Micro Focus\\LoadRunner\\bin\\mdrv.exe" 
                    -usr "C:\\Scripts\\CheckoutFlow.usc" 
                    -suffix ${BUILD_NUMBER} 
                    -log_on_failed_test 
                    -output_dir "C:\\Results\\Build_${BUILD_NUMBER}"
                    '''
                }
            }
            post {
                success {
                    archiveArtifacts artifacts: 'C:\\Results\\Build_*\\*.lrr', allowEmptyArchive: false
                }
            }
        }
    }
}

上述脚本在每次代码提交后自动执行购物车业务流的压力测试,并将结果归档。结合后续的Analyzer CLI调用,还可实现自动判读:

analyzer -result "C:\Results\Build_123.lrr" -slareport "SLA_Status.html" -fail_if_violated

若SLA不满足(如登录响应时间>3s),则返回非零退出码,直接中断部署流程。

同时,利用Git对VuGen脚本进行版本管理已成为最佳实践。建议采用以下分支策略:

  • main :存放已验证稳定的基准脚本
  • feature/* :开发新业务逻辑时创建特性分支
  • hotfix/* :紧急修复参数化错误或检查点失效

并通过Git Hooks强制要求提交前执行本地回放验证:

#!/bin/bash
# .git/hooks/pre-commit
if ls *.usr >/dev/null 2>&1; then
    for script in *.usr; do
        echo "Validating $script..."
        mdrv -usr "$script" -run_local -stop_on_error
        if [ $? -ne 0 ]; then
            echo "Validation failed for $script"
            exit 1
        fi
    done
fi

这种机制确保了所有进入仓库的脚本都具备基本可执行性,降低了协作冲突风险。

5.4 高效脚本维护与最佳实践总结

随着系统迭代加速,VuGen脚本数量往往呈指数增长。为避免陷入“脚本泥潭”,必须推行模块化设计原则。

推荐采用“主控+子模块”的分层结构:

Scripts/
├── Lib/
│   ├── LoginUtils.c
│   ├── PaymentProcessor.c
│   └── DBValidator.c
├── Scenarios/
│   ├── Guest_Checkout.usc
│   └── Member_Recharge.usc
└── Data/
    ├── Users.dat
    └── Products.json

在主脚本中通过 lr_load_dll extern 引入公共函数库:

// Guest_Checkout.c
extern void login_as_guest();
extern int verify_order_status(char* orderId);

vuser_init()
{
    lr_load_dll("Lib/LoginUtils.dll");
    return 0;
}

Action()
{
    login_as_guest();
    web_add_auto_header("Authorization", lr_eval_string("{JWT_TOKEN}"));
    lr_start_transaction("Submit_Order");
    web_submit_data("PlaceOrder",
        "Action=https://api.store.com/orders",
        "Method=POST",
        ITEMDATA,
        "Name=productId", "Value={SELECTED_PRODUCT}", ENDITEM,
        LAST);
    lr_end_transaction("Submit_Order", LR_AUTO);
    verify_order_status(lr_eval_string("{ORDER_ID}"));
    return 0;
}

编译时使用外部构建脚本统一打包:

@echo off
for /f "tokens=*" %%f in ('dir Lib\*.c /b') do (
    gcc -c Lib\%%f -o Lib\%%~nf.o -I"%LR_HOME%\include"
)
ar rcs Lib\shared_lib.a Lib\*.o

该方式使得多个场景可共享同一套底层逻辑,修改登录流程时只需更新 LoginUtils.c 一次即可全局生效。

在负载建模方面,应摒弃“固定Ramp-up”这类粗粒度策略,转而采用基于真实APM数据的动态模型。例如,从生产环境采集一周内每小时并发用户数,拟合出泊松分布参数λ,然后在Controller中配置按概率触发的Vuser调度规则。

最终形成的多维度负载模型应涵盖:
- 峰谷周期(早高峰、午休、晚间促销)
- 地域延迟差异(北京vs新疆用户网络RTT)
- 设备类型占比(移动端60%,PC端40%)

此类精细化建模不仅能更准确预测系统极限,也为后续的弹性扩缩容提供了科学依据。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:LoadRunner是由Micro Focus开发的企业级负载与性能测试工具,广泛应用于系统稳定性评估、压力测试和容量规划。本系列视频教程“LoadRunner性能测试视频2”深入讲解LoadRunner的核心组件与工作流程,涵盖虚拟用户脚本录制、测试场景设计、性能指标监控及结果分析等关键内容。通过实际操作演示,帮助测试人员掌握VuGen脚本编写、Controller场景管理、Analyzer报告解读,并结合断言调试、异常处理与CI工具集成,提升自动化测试效率。教程强调最佳实践,助力IT专业人员构建高效、可靠的性能测试体系。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐