跳转至

LoadRunner 场景设计与 SLA 分析

脚本能回放通过,只说明协议层没问题;场景设计错了,跑出来的报告照样不能用。这篇按 Controller 的实际操作路径讲:场景类型怎么选、Pacing 和思考时间怎么组合、集合点什么时候会把人卡死、SLA 怎么定才不是自欺欺人,以及 Analysis 里七张图的判读顺序。环境为 LoadRunner 2023(24.1)Controller + Analysis,被测系统为 4 节点 Spring Boot 集群。

一、三个现场问题

1.1 500 Vuser 跑出 120 TPS,业务方以为系统不行

场景:500 Vuser,4 个脚本按比例混合,Runtime Settings 里 Pacing 设为 “After previous iteration ends, wait 5 seconds”,思考时间按录制回放,平均 2.6 秒,单次迭代事务耗时 0.9 秒。

单 Vuser 周期 = 0.9 + 2.6 + 5 = 8.5 秒,500 Vuser 的理论 TPS 上限:

TPS = 500 / 8.5 ≈ 58.8 事务/秒

每个迭代含 2 个事务,报告里的事务 TPS 约 117,和实测 120 对得上。系统没问题,是 Pacing 把压力锁死了。把 Pacing 改成 “As soon as the previous iteration ends”,周期降到 3.5 秒,同样 500 Vuser 的理论吞吐升到 285 事务/秒(142 迭代/秒,每迭代 2 个事务)。

1.2 SLA 全绿,用户还是投诉

SLA 只配了 “Average Transaction Response Time < 2s”,报告显示平均 680ms,通过。但 Analysis 里 90% 分位是 3.4 秒,登录事务的 P95 是 5.1 秒。平均值被大量 200ms 的查询请求拉平了,长尾完全没进 SLA。

1.3 集合点让场景一直不结束

lr_rendezvous("buy_now");

场景配了 100 Vuser,集合点人数设成 200,Timeout 用默认。结果所有 Vuser 都停在集合点,直到集合点超时才放行,报告里多出一大批 5 分钟以上的“事务”。另外一次是 Vuser 数刚好等于集合点人数,但其中一个 Vuser 在前置请求就失败了,剩下 99 个永远等不齐。

这两类问题的共同点:集合点是“等待”,不是“加速”,人数配错只会制造假的超时。

二、Controller 场景类型

术语对照:LoadRunner 的 Controller 是一个独立的场景执行管理组件(管 Vuser、集合点、SLA、Load Generator)。JMeter 没有同名组件:对应角色是启动 jmeter -n -t ... 的 master(客户端)+ jmeter-server worker;JMeter 里的 "Controller" 指 Transaction Controller 这类逻辑控制器,两者不是一回事。

2.1 手动场景(Manual Scenario)

路径:Controller → File → New Scenario → Manual Scenario。

配置项 真实含义 注意
Scripts 列表 参与本次压测的脚本 每个脚本可设不同 Quantity
Quantity 该脚本分配的 Vuser 数 是 Vuser,不是 TPS
Group 名称 用于分组启停、分组监控 同脚本也可以拆成多个 Group
Initialize all Vusers before run 全部初始化完成后再开始计时 不勾选时,先初始化完的 Vuser 会提前发请求,Ramp-Up 曲线失真
Start group / Stop group 场景运行中手动启停某一组 用于“先停支付、再停下单”的故障演练
Duration 场景持续时间 到点后停止发压,不是立即杀进程

手动场景适合:已知目标并发、需要精确控制每组 Vuser、需要中途改配比。

2.2 面向目标场景(Goal-Oriented Scenario)

路径:新建场景时选 Goal-Oriented Scenario,再点 Edit Scenario Goal。

Goal Type 目标写法 适用 坑
Virtual Users 达到 N 个 Vuser 验证固定并发下的表现 本质还是手动场景
Transactions per Second 达到 N 事务/秒 按业务 TPS 验收 Controller 自动加 Vuser,可能加到授权上限
Transaction Response Time 某事务平均 RT 不超过 N 秒 反推系统能承载多少 Vuser 达到目标后不再加压,测不出拐点
Hits per Second 达到 N 请求/秒 页面型业务 Hits 含静态资源,口径要和业务对齐
Pages per Minute 每分钟页面数 传统 Web 现代 SPA 场景不适用
KB per Second 吞吐字节数 下载、视频类 受网络带宽限制明显

Goal 的 “Reach goal” 有两种方式:

  • Automatically:Controller 直接跳到目标负载,曲线是台阶状,不适合看拐点。
  • Gradually:按步长逐步逼近,能看出 TPS 与 RT 的关系,推荐。

判定标准:面向目标场景结束时必须看 Goal Report,确认 “Actual” 是否真的达到 “Goal”。没达到就说明系统在当前配置下扛不住,不要拿“场景跑完了”当通过。

2.3 百分比模式

Scenario → Convert Scenario to Percentage Mode,把每个脚本的 Vuser 数改成百分比。适合业务配比固定的混合场景,例如浏览 60%、加购 20%、下单 15%、支付 5%。

注意百分比换算后是整数 Vuser,500 × 5% = 25,配比精度受总 Vuser 数限制;100 Vuser 时 5% 只能取 5,实际误差可能到 1%。

三、Pacing 与 Think Time:决定 TPS 的两个旋钮

3.1 概念先分清

概念 定义 配置位置
Think Time 一次迭代内、两个请求之间的“用户思考”等待 Runtime Settings → Think Time
Pacing 两次迭代之间的间隔或迭代启动节奏 Runtime Settings → Pacing

Think Time 影响的是事务内部的请求间隔,Pacing 影响的是迭代与迭代之间。两者都会拉长周期、降低 TPS,但作用点不同,调优时必须分开看。

3.2 Think Time 的四种回放方式

方式 行为 适用
Ignore think time 完全忽略,请求背靠背 极限压力、找最大吞吐
As recorded 按录制时的真实间隔 常规负载、稳定性
Multiply recorded think time by N 统一乘以系数 想放大/缩小用户间隔
Use random percentage of recorded 在指定百分比区间随机 模拟真实用户的不均匀节奏

稳定性测试建议用 As recorded 或 Random percentage 50%–150%。全部 Ignore 会把一个浏览型业务压成 API 轰炸,测出来的 RT 不能代表线上。

3.3 Pacing 的四种模式

模式 计时起点 实际周期
As soon as the previous iteration ends 上一迭代结束 事务耗时 + Think Time
After previous iteration ends, wait N seconds 上一迭代结束 事务耗时 + Think Time + N
At fixed intervals of N seconds 上一迭代开始 max(N, 事务耗时 + Think Time)
At random intervals of N–M seconds 上一迭代开始 max(随机值, 事务耗时 + Think Time)

最容易误解的是第三种:At fixed intervals 是从迭代开始计时,如果 N 小于单次迭代耗时,Pacing 根本不起作用,实际周期就是迭代耗时。很多人配了 fixed 1s 以为限速了,其实没有任何效果。

3.4 组合与算例

设单次迭代事务耗时 T=0.9s,Think Time S=2.6s,Vuser 数 N=500。

Pacing 配置 迭代周期 单 Vuser TPS 500 Vuser 迭代 TPS
ASAP + Ignore think 0.9 1.11 555
ASAP + As recorded 3.5 0.286 143
After end + 5s + As recorded 8.5 0.118 59
Fixed 5s + As recorded max(5, 3.5)=5 0.2 100
Fixed 2s + As recorded max(2, 3.5)=3.5 0.286 143

结论:

  • 想让 TPS 可控,用 Fixed intervals 最直观,但要保证间隔大于单次迭代耗时。
  • 想模拟真实用户,用 After previous iteration ends + 随机延迟,别用固定值。
  • 报告里写 TPS 时必须同时写 Pacing 和 Think Time 配置,否则数字无法复现。

3.5 迭代次数怎么定

Runtime Settings → General → Run Logic 里可以设 Number of Iterations,也可以靠场景 Duration 控制。两者同时存在时,先到者结束。稳定性场景建议用 Duration(例如 8 小时),迭代次数设 Forever,否则迭代次数跑完会提前结束,报告时长不够。

四、集合点(Rendezvous)

4.1 脚本写法

Action()
{
    lr_start_transaction("buy");

    lr_rendezvous("buy_now");        /* 集合点必须在事务开始之后、下单请求之前 */

    web_submit_data("create_order",
        "Action=http://shop.example.com/api/order",
        "Method=POST",
        "EncType=application/json",
        ITEMDATA,
        "Name=skuId", "Value={sku}", ENDITEM,
        LAST);

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

位置很关键:

  • 放在 lr_start_transaction 之前:集合等待时间不计入事务,但集合点本身不在事务内,报告里看不到它对 RT 的影响。
  • 放在事务内部、请求之前:等待时间计入事务 RT,能真实反映“用户等待开抢”的体验,但 P95 会被集合等待拉高。
  • 放在事务之后:完全没有意义。

推荐放在事务内部,并在报告里注明“buy 事务包含集合等待”。

4.2 Controller 侧的集合点策略

Controller → Scenario → Rendezvous 可以查看每个集合点的状态,并设置释放策略:

策略 行为
Vuser count 凑够指定人数才释放
Percentage of Vusers 凑够总 Vuser 的百分比才释放

场景运行时,Rendezvous 窗口会显示 “Waiting” 的 Vuser 数。如果这个数字长时间不下降,基本可以判定人数配错或有 Vuser 卡在前置请求。

4.3 死锁条件与判定

条件 结果
集合点人数 > 场景 Vuser 总数 永远等不齐,直到超时
集合点人数 = Vuser 总数,但有 Vuser 提前失败退出 剩余 Vuser 永远等不齐
集合点人数 = Vuser 总数,且脚本有分支 分支未走到的 Vuser 不参与集合,仍会卡住
Timeout 设为 0 或极大值 场景挂死,只能强行停止

判定标准:集合点人数应小于等于“必然到达该点的最小 Vuser 数”,并显式设置一个可接受的超时(例如 30–60 秒)。超时后 LR 会记录 Rendezvous timeout,这批样本的 RT 不能用于容量结论。

4.4 集合点制造的到底是什么

200 个 Vuser 同时释放,瞬间并发是 200 个请求,但如果每个请求 300ms,这波请求在 300ms 内就消化完了,持续 TPS 仍然是 200/0.3 ≈ 667 的瞬时值,下一波要等下一轮迭代。所以:

  • 集合点验证的是瞬时抗冲击能力(连接队列、线程池、限流),不是持续容量。
  • Hits per Second 图上会看到尖刺,Transactions per Second 图上不会持续走高。
  • 想验证持续高 TPS,用 Pacing 和 Vuser 数,不要用集合点。

五、负载生成器(Load Generator)

5.1 连接与容量

Controller 通过 54345 端口连接 LG。检查命令:

Get-Service | Where-Object { $_.Name -like "*agent*" -or $_.DisplayName -like "*LoadRunner*" }
netstat -ano | findstr :54345

Linux LG:

ps -ef | grep -i magent
ss -lntp | grep 54345

容量经验值:

机器规格 建议 Vuser 上限 判定
4C8G 300–500 CPU 持续 < 50%
8C16G 800–1200 CPU 持续 < 60%
16C32G 2000–3000 需拆分协议与网络

这不是授权限制,而是实测安全线。LG 的 CPU 一旦超过 70%,Error -27796: Failed to connect to server 和 Error -27728: Step download timeout 会成片出现,看起来像服务端挂了,实际是压测机发不出去。

5.2 用脚本确认落在哪台 LG

int vuser_id = 0;
char *group_name = NULL;
int scenario_id = 0;

lr_whoami(&vuser_id, &group_name, &scenario_id);
lr_output_message("LG=%s vuser_id=%d group=%s ip=%s",
    lr_get_host_name(),
    vuser_id,
    group_name ? group_name : "null",
    lr_get_vuser_ip() ? lr_get_vuser_ip() : "n/a");

lr_whoami 的第二个参数是 char **,传 NULL 也可以,但想打印组名就必须传一个有效指针。多台 LG 时,每个 Vuser 的输出落在各自机器的日志里,不要只在 Controller 上找。

5.3 IP Spoofing

单机多 IP 用于绕过服务端的单 IP 限流或连接数限制:

Controller → Scenario → Load Generators → Enable IP Spoofing

前提是 LG 上已经绑定了多个 IP(netsh interface ip add address),否则 LR 启动时会报无法分配 IP。开了 IP Spoofing 后,服务端的会话粘滞、白名单策略都可能失效,先在测试环境验证。

六、监控计数器

6.1 Windows(PerfMon 计数器)

在 Controller 的 Run → Performance Counters(或 Analysis 的监控图)里添加,路径必须写全:

计数器 含义 预警阈值
\Processor(_Total)\% Processor Time CPU 总利用率 持续 > 75%
\System\Processor Queue Length 处理器排队线程数 持续 > 2 × 核数
\Memory\Available MBytes 可用物理内存 < 10% 总量
\Memory\Pages/sec 换页频率 持续 > 100
\PhysicalDisk(_Total)\% Disk Time 磁盘繁忙度 持续 > 70%
\PhysicalDisk(_Total)\Avg. Disk Queue Length 磁盘排队 持续 > 2
\Network Interface(*)\Bytes Total/sec 网卡吞吐 接近带宽上限 70%
\TCPv4\Connections Established 已建立连接数 接近 somaxconn / 端口上限
\.NET CLR Memory(_Global)\% Time in GC GC 时间占比 持续 > 10%

Processor Queue Length 比 CPU% 更能反映饱和:CPU 80% 但队列为 0,说明还能扛;CPU 60% 但队列长期大于核数,说明线程在等 CPU 或锁。

6.2 Linux

LR 原生的 Linux 监控依赖 rstatd,现代发行版基本不可用,实践上用 nmon 或 sar 采集后再对照 Analysis 时间轴:

# 每 5 秒采集一次,共 720 次(1 小时)
nmon -f -s 5 -c 720 -m /var/log/nmon

# CPU、内存、磁盘、上下文切换
sar -u 5 720
sar -r 5 720
sar -d -p 5 720
vmstat 5 720

# 只看 Java 进程
pidstat -p $(pgrep -f 'java.*shop' | head -1) 5 720

判定时对齐时间轴:nmon 的第一条记录时间要和场景开始时间对齐,否则“CPU 峰值出现在 14:32”和“TPS 拐点在 14:35”会错位三分钟,结论完全相反。

6.3 应用层计数器

指标 采集方式 关注点
JVM GC jstat -gcutil <pid> 1000 Full GC 次数与停顿
堆内存 jcmd <pid> GC.heap_info 老年代是否持续增长
数据库连接池 HikariCP /actuator/metrics/hikaricp.connections.active 活跃连接是否打满
Tomcat 线程池 /actuator/metrics/tomcat.threads.busy busy 是否接近 max
Redis 命中率 INFO stats 的 keyspace_hits/misses 命中率骤降
MQ 堆积 rabbitmqctl list_queues ready 消息持续增长

只压不监控,报告里只有 RT 和 TPS,无法回答“为什么”。SLA 失败时也没法定位。

七、Analysis 关键图表解读

7.1 七张图的分工

图表 回答什么问题 判读要点
Transaction Response Time 用户体验如何 看分位线与分布,不看平均线
Running Vusers 加压是否符合设计 曲线应与 Ramp-Up 计划一致
Hits per Second 请求速率与突发 含静态资源,和 TPS 不同口径
Throughput 字节吞吐 判断是否网络受限
Transactions per Second 业务处理能力 找平台段与拐点
Errors per Second 失败发生在什么时候 与 TPS 拐点对齐
Web Page Diagnostics 时间花在哪 有额外开销,只在诊断轮开启

7.2 Transaction Response Time

Analysis 默认画的是平均值。必须手动加 90%/95% 分位:

右键图 → Add Measures → Transaction Response Time (Percentile) → 选择 90 / 95

判读方法:

  • 平均线平稳、P95 持续抬升:长尾恶化,通常是 GC、锁等待或慢 SQL。
  • 所有分位线同时陡增:整体饱和,看 CPU/连接池。
  • 曲线呈周期性尖刺:定时任务、缓存集中失效、连接池回收。
  • 某个事务的 RT 恒等于 Pacing 间隔:脚本把等待算进了事务,检查 lr_start_transaction 的位置。

7.3 Running Vusers

RUNNING Vusers 曲线应该和设计一致。如果 500 Vuser 场景的曲线最高只到 480,说明有 20 个 Vuser 初始化失败或卡在集合点;如果曲线提前下坠,说明有 Vuser 因错误退出(Continue on error 没勾选)。

7.4 Hits per Second 与 Throughput

  • Hits per Second 统计的是 HTTP 请求数,包含 JS/CSS/图片。一个页面 1 个 HTML + 20 个资源,Hits 是 21,业务事务只有 1。
  • Throughput 单位是字节/秒。当 TPS 上不去、Throughput 却贴近网卡带宽时,瓶颈在网络或响应体过大。
  • 两者同时下降而 Running Vusers 不变,说明请求被阻塞(连接池、线程池、下游超时)。

7.5 图表关联(Correlate)

Analysis 支持把两张图合并:

选中 Transactions per Second → 右键 → Merge Graphs → 选择 Running Vusers

常用组合:

组合 能看出什么
TPS + Running Vusers 加人是否带来吞吐增长
TPS + Average RT 拐点位置
TPS + Errors per Second 失败是否由饱和引起
Throughput + Hits per Second 平均响应体大小变化

粒度(Granularity)会影响尖刺可见性。默认 1 分钟粒度会把 10 秒的尖峰抹平,诊断时把粒度调到 5–10 秒,但样本量太小会导致曲线抖动,最终结论仍以 1 分钟为准。

八、SLA 配置与报告

8.1 在 Controller 里定义 SLA

路径:Controller → Scenario → SLA → New。

Goal Type 阈值示例 说明
Average Transaction Response Time < 2 s 最常用,但会掩盖长尾
Transaction Response Time (Percentile) 90% < 3 s 推荐,能覆盖大多数用户体验
Errors per Second < 1 关注瞬时错误
Total Errors < 0.1% 关注整体质量
Hits per Second > 500 验证吞吐下限

SLA 还要选 Load Conditions:

  • Whole scenario:整场平均,最宽松。
  • Time range:只统计稳态段,推荐。
  • Vuser range:只统计某个并发区间,用于验证“低负载下必须达标”。

8.2 一个可用的 SLA 组合

事务:order_create
  Average RT        < 1.5 s
  90th Percentile   < 2.5 s
  95th Percentile   < 4.0 s
  错误率            < 0.1%
  TPS               >= 300(稳态 30 分钟)

全局:
  Total Errors      < 0.5%
  CPU(应用节点)    < 75%

只配 Average 的 SLA 等于没配。上面的 1.2 节就是例子:平均 680ms 全绿,P95 已经 5 秒。

8.3 SLA 报告怎么读

运行结束后 Results → Analyze Results 打开 Analysis,左侧树里的 SLA Report:

列 含义 判读
Goal 设定的阈值 与需求文档一致
Actual 实测值 注意统计区间
Status Pass / Fail 单个区间失败即整体不达标
Measurement Interval 统计粒度 默认 1 分钟,可改

三个容易误读的点:

  1. SLA 是按区间判定的,整体平均通过不代表每个区间通过。报告里出现零星的 Fail,要看对应时间点是否与尖峰重合。
  2. SLA 的 RT 包含 Think Time 和 Pacing 吗?取决于事务边界。lr_start_transaction 之后的等待才算,脚本里把 lr_think_time 放进事务,SLA 就会被思考时间污染。
  3. SLA 通过不等于用户体验达标。SLA 只覆盖你定义的事务,未登录、未下单的路径不在统计内。

九、一套真实场景参数表

被测系统:4 节点应用 + 1 主 2 从数据库,目标峰值 600 TPS(下单事务)。

脚本 业务占比 Vuser Think Time Pacing 事务边界
browse 60% 300 As recorded(均值 3.2s) Fixed 6s 首页 + 详情
cart 20% 100 As recorded(均值 2.4s) Fixed 8s 加购
order 15% 75 As recorded(均值 1.8s) Fixed 10s 创建订单
pay 5% 25 As recorded(均值 2.0s) Fixed 12s 支付回调

Ramp-Up:10 分钟内线性加到 500 Vuser,保持 60 分钟,最后 2 分钟线性停止。集合点只加在 order 脚本的“提交订单”前,人数 50,Timeout 45 秒,仅在尖峰场景启用。

对应 SLA:

order_create: P90 < 2.5s, P95 < 4s, 错误率 < 0.1%
pay_callback: P90 < 3s, 错误率 < 0.05%
browse:       P90 < 1.5s
全局 TPS >= 600(稳态 30 分钟)

LG:2 台 8C16G,各 250 Vuser,CPU 控制在 55% 以下。

十、瓶颈判断顺序

按“先排除自己,再怀疑别人”的顺序,能少走很多弯路:

  1. 压测机:LG CPU > 70%、Error -27796 成片、netstat 显示端口耗尽 → 加 LG 或降 Vuser。
  2. 网络:Throughput 贴近带宽、RT 均匀增加、无错误 → 抓包看重传(netstat -s 的 segments retransmitted)。
  3. 应用 CPU:CPU 饱和且 TPS 不再增长、Processor Queue Length 大于核数 → 看热点方法(arthas profiler/thread)。
  4. JVM:Full GC 频繁、GC 时间占比 > 10%、老年代持续增长 → 调堆/查泄漏。
  5. 线程池/连接池:Tomcat busy 接近 max、Hikari active 等于 maximumPoolSize、请求在排队 → 扩容或缩短事务。
  6. 数据库:慢查询、锁等待、连接数打满、主从延迟 → SHOW PROCESSLIST、SHOW ENGINE INNODB STATUS、慢日志。
  7. 缓存/MQ/下游:Redis 命中率下降、MQ 堆积、下游 RPC 超时 → 看依赖服务的 RT 与错误率。
  8. 限流/熔断:错误码集中在 429/503,TPS 被人为压平 → 确认阈值是否按容量设计。

判定标准:只有“TPS 平台 + RT 拐点 + 错误率上升 + 资源饱和”四条同时出现,才能说找到了容量上限。只有一条,通常只是某个局部瓶颈。

十一、报告结论模板

场景:混合业务,500 Vuser,Ramp-Up 10 分钟,稳态 60 分钟
结果:稳态 TPS 612,order_create P90 1.9s / P95 3.2s,错误率 0.04%
SLA:order_create 全部通过;pay_callback P95 3.8s 超标(阈值 3s)
瓶颈:应用节点 CPU 78%,Hikari 活跃连接在 450 Vuser 时达到 100/100
证据:TPS 在 14:32 出现平台,RT 同分钟抬升,Errors per Second 同步上升
建议:连接池 100 → 150,下单 SQL 增加覆盖索引后复测;LG 增加 1 台

结论必须包含:场景参数、稳态口径、分位数、SLA 逐项结果、瓶颈证据链、下一步动作。缺任何一项,报告都只能当“跑过了”的证明,不能当决策依据。

十二、坑位表

坑 现象 规避
Pacing 用 After end + N 却没算事务耗时 TPS 比预期低很多 用 TPS = Vuser / (T + S + N) 先算一遍
Fixed intervals 小于迭代耗时 Pacing 形同虚设 保证 N > T + S
Think Time 全 Ignore RT 偏低、TPS 虚高 至少按录制回放或随机百分比
集合点人数 > Vuser 数 场景挂死/大量超时 人数 ≤ 必然到达的最小 Vuser 数,并设 Timeout
集合点放在事务外 报告看不到瞬时冲击 放事务内,报告注明
SLA 只配平均 RT 长尾超标仍显示通过 至少加 P90/P95
SLA 统计区间含 Ramp-Up 前期错误拉低整体 用 Time range 只统计稳态
开 Web Page Diagnostics 跑正式场景 LG CPU 飙高、TPS 上不去 只在诊断轮开启
多 LG 时钟不同步 图表时间轴错位 统一 NTP,采集前校时
迭代次数与 Duration 同时设置 场景提前结束 稳定性场景用 Duration + Forever
场景结束直接关 Controller 结果文件不完整 等 Results 落盘后再退出

十三、检查清单

  • 场景类型与测试目标匹配(手动/面向目标/百分比)
  • 每个脚本的 Pacing、Think Time 已换算成理论 TPS,并与目标比对
  • Ramp-Up 曲线在 Running Vusers 图里与设计一致
  • 集合点人数、Timeout、事务边界均已确认,并做过一次空跑
  • LG 数量与规格满足 Vuser 需求,CPU 余量 ≥ 30%
  • Windows/Linux 计数器已添加,时间轴与场景对齐
  • SLA 覆盖平均、P90/P95、错误率、TPS,且限定稳态区间
  • Analysis 中已加 P90/P95 曲线,未只看平均值
  • 报告写明场景参数、统计口径、瓶颈证据链
  • 结果目录、jtl/lrr 文件已归档,环境版本已记录

相关阅读