2026/8/21大约 6 分钟
一、性能测试基础理论
1.性能测试的指标有哪些?
- 响应时间(RT):平均、P90/P95/P99。
- 吞吐量:TPS(每秒事务数)、QPS(每秒查询数)、RPS。
- 并发数/并发用户数、错误率、资源使用率(CPU、内存、磁盘 IO、网络、连接数)。
2.TPS、QPS、并发用户数的区别?
- QPS 偏查询类请求量;TPS 偏事务(一个事务可含多个请求);并发用户数指同时在线/同时操作的用户量,不等于 QPS,需要结合业务模型换算(如思考时间)。
3.如何制定性能测试方案?
- 明确测试目标与场景(基准、负载、压力、稳定性、容量)→ 分析业务模型(用户比例、接口比例、高峰时段)→ 设计脚本(参数化、关联、思考时间)→ 确定指标与阈值 → 执行 → 瓶颈定位 → 调优与回归。
如何做稳定性(长时间)测试?
- 以 70%-80% 的预期峰值负载持续运行 8-24 小时以上,监控内存泄漏(GC 曲线逐步升高)、连接泄漏、缓存雪崩、MQ 堆积、响应时间劣化趋势。
如何测试接口的响应时间波动 / 毛刺?
- 看 P99/P95 而非平均;配合并发阶梯(逐步加压)观察拐点;检查是否触发 GC、慢查询、冷缓存、外部服务抖动。
二、性能测试监控
三、线上性能测试瓶颈分析
常见的性能瓶颈有哪些?
- 数据库:慢 SQL、缺索引、锁竞争、连接池打满。
- 应用:线程池/连接池耗尽、代码耗时(序列化、循环、日志)、GC 频繁、缓存未命中、线程阻塞、死锁、内存泄露
- 中间件:MQ 堆积、Redis 大 key/热 key、Nginx 配置。
- 硬件基础设施:cpu 过高、内存不足、带宽满载、磁盘 IO慢。
性能瓶颈如何定位?(高频)
- 分层排查:由外到内——客户端 → 网关/负载均衡 → 应用 → 中间件 → 数据库 → 操作系统资源。
- 手段:压测工具看指标趋势;APM(如 SkyWalking、Arthas)链路追踪;慢日志(DB/Redis);线程栈 dump 分析;监控面板(CPU、内存、IO)。
- 定位到模块后,再看是锁、算法复杂度、还是外部依赖耗时。
OOM 如何做性能分析?(Java应用)
- OOM(OutOfMemoryError):JVM 堆内存不足(
Java heap space)、元空间不足(Metaspace)、栈溢出(StackOverflowError)、无法创建本地线程(unable to create new native thread)等。 - 分析步骤:
- 启动时添加 JVM 参数开启转储:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/dump.hprof,让 OOM 时自动导出堆转储文件。 - 用 MAT(Memory Analyzer Tool)分析 hprof:查看 Dominator Tree(支配树) 找大对象、Leak Suspects(泄漏嫌疑) 自动定位可疑泄漏点。
- 结合 GC 日志(
-Xlog:gc*)看堆使用趋势:Full GC 频率是否剧增、回收后内存是否无法回落。 - 定位代码:大集合/缓存无限增长、静态字段持有对象、未关闭的 IO/连接、ThreadLocal 未清理、第三方库持有引用等。
- 结合压测复现:在压测场景下观察内存曲线,确认 OOM 是否与并发量/数据量相关。
- 启动时添加 JVM 参数开启转储:
- 常见原因:集合类只增不减、缓存无淘汰策略、SQL 一次性加载大结果集、字符串/字节数组拼接放大内存、线程数过多导致栈内存溢出。
分析 Java 程序内存时,如何区分正常内存增长和内存泄露增长?
- 正常增长:堆使用率随流量/数据量波动,GC 后内存能回落到基线水平,曲线呈"锯齿状"但有上下限,长期运行不持续走高。
- 内存泄露增长:每次 GC 后内存基线不断抬升,回收后无法回到原水平,曲线呈
"阶梯上升"趋势,最终趋于 OOM。 - 判别方法:
- 观察 GC 后堆大小趋势(
jstat -gcutil/ GC 日志):连续多次 Full GC 后 heap used 是否持续增加。 - 对比基线:在相同压测负载下,比较不同时间段 GC 后的稳定堆占用。
- 用 MAT 做对比分析:在不同时间点导出两份 hprof,比较对象直方图(Histogram)差异,看哪些对象数量/大小在增长。
- 长稳测试:连续运行数小时到数天,若堆使用率单调递增且 GC 回收不掉,即可判定为泄漏;若波动平稳则为正常。
- 观察 GC 后堆大小趋势(
- 补充:正常增长也可能是"临时大对象 + 晋升到老年代过多",需要结合对象年龄与晋升率判断,不一定是泄漏。
JVM 的 GC 回收原理和机制?
- 分代收集理论:大部分对象"朝生夕灭",按对象存活时间划分区域,不同区域采用不同回收策略:
- 新生代(Eden + 两个 Survivor):对象优先在此分配,使用复制算法,存活对象在 Eden 与 Survivor 间复制,晋升阈值(默认 15 次)满后进入老年代。
- 老年代:存放长期存活对象,用标记-清除 / 标记-整理算法,算法触发的条件:老年代空间不足、大对象直接进入、晋升失败、Full GC。
- 元空间/方法区:存放类元数据、常量池,不足时触发 Metaspace 回收。
- 可达性分析算法:以 GC Roots(栈帧局部变量、静态变量、JNI 引用、活跃线程等)为起点向下搜索,不可达的对象判定为可回收;配合引用类型(强、软、弱、虚引用)决定回收时机。
- 常见收集器:
- Serial / Parallel(JDK8 默认):多线程并行回收,STW 较长。
- CMS:并发标记清除,减少 STW,但会产生碎片。
- G1(JDK9+ 默认):将堆划分为 Region,按 Region 收集,可预测停顿(
-XX:MaxGCPauseMillis),兼顾吞吐与低延迟。 - ZGC / Shenandoah:超低停顿(毫秒级),适合大堆、低延迟场景。
STW(Stop The World)机制:GC 标记/清理阶段需要暂停业务线程,暂停时长是调优核心指标;调优方向:合理堆大小、对象分配速率、回收器选型、避免大对象与频繁 Full GC。
- 排查手段:开启 GC 日志(
-Xlog:gc*)、jstat观察各代使用率与 GC 次数、jmap导出堆、Arthas 在线诊断。
四、性能测试工具
1.Jmeter中如何实现参数关联? 【登录token如何传递给下一个接口?】
- 常规考察重点:
- 参数化:CSV 数据集、JDBC 数据库、Blazemeter 云端数据集 的使用
- `前置处理器`关联场景: 请求业务接口需要登录token,需要在请求头中传递token
- `后置处理器`关联场景: 分页查询商品 -> 点击商品详情。正则提取、JSON 提取、BeanShell、JDBC 提取、XPath 提取、XPath 提取、JSR223 脚本 , 获取具体的值做断言处理Star 描述
面试亮点:基于AI的全链路性能测试提效:7个 Skill技能,亲测好用,实现全链路压测落地
2.JMeter如何模拟多用户并发登录?
什么是全链路压测?和普通压测的区别?
- 在生产环境或独立影子环境上,对整条业务链路(网关→应用→中间件→DB)进行高仿真压测,使用影子流量/影子表隔离测试数据。
- 比单接口压测更接近真实,能发现跨服务瓶颈(如某个环节成为短板)。