如果现在让 AI 帮你写一份 JMeter 脚本,粘贴到命令行直接跑,你会得到什么?大概率是一份看起来很完整的.jmx文件:有线程组、有 HTTP 请求、有聚合报告,甚至还有注释。但等你真的把它放到压测环境,可能连第一个请求都发不出去——CSV 参数化路径是错的,断言写成了响应码校验,Header 里还带着 AI 编造的假 Token。
这不是 AI 能力不够,而是你直接把一个缺少上下文约束的 AI 当成了性能测试工程师。AI 当然能做性能测试,但它更像一个“执行能力很强、但没有工程经验的新人”。真正能让它稳定产出可运行、可度量、可分析结果的方案,是把你脑中的经验、规则、判断标准,沉淀成一个叫Skill的结构化技能包,再让 AI 按照这套流程去干活。
这篇文章不会停在“AI 能生成 JMeter 脚本”这种表面结论上。我会从一个最常见的压测场景出发,完整演示如何用 Skill 驱动的方式,把“需求分析 → 脚本生成 → 脚本校验 → 压测执行 → 结果解析 → 瓶颈定位”这条链路走通,并给出可以直接复用的工程模板。如果你正打算让 AI 参与性能测试,或者已经在用但经常被低质量脚本坑,这篇文章值得收藏。
1. 这篇文章真正要解决的问题
很多人对“AI 做性能测试”的理解,其实停留在“让 AI 写一段脚本”这一个节点上。搜索出来的教程也大多在演示同一个流程:把接口信息粘贴给 AI,AI 返回一段 JMeter 脚本,复制保存,运行,结束。
但真实项目中的性能测试根本不是这样运作的。
一个接口要压测,首先要确认压测目标是什么:是验证稳定运行 30 分钟无内存溢出,还是看它能不能撑住双十一峰值的 2 倍流量?其次要确认请求数据怎么准备:用固定参数刷量,还是从线上日志采样后脱敏?还要确认断言怎么写:是只校验 HTTP 200,还是要校验业务返回码、响应时间分布?最后还要关注执行完怎么看数据:聚合报告算出来的 P95 到底可信不可信,异常率暴涨是先看数据库还是先看网关?
这些判断,AI 默认全都不做。它只会根据你给的一句话,生成一份“看起来很专业”的默认脚本。于是 AI 做性能测试的真实痛点变成了三个:
- 脚本能用,但业务含义不对。压测一个订单查询接口,AI 可能在每个请求里都用同一张订单号,数据库根本没压力,Redis 缓存命中率却高到不真实。
- 流程断裂,生成完就结束。AI 只负责“生成”,不负责“验证”和“分析”。脚本跑出异常率 30% 时,AI 不会主动帮你定位是断言问题、参数化问题还是服务真的扛不住。
- 经验无法沉淀。每次让 AI 生成脚本,都是从零开始对话。这个团队踩过的坑、验证过的参数范围、总结过的压测规范,AI 完全记不住。
所以这篇文章要解决的核心问题,不是“AI 能生成性能测试脚本吗”,而是:怎么把 AI 从“能写脚本的对话机器”,改造成“遵守你们团队性能测试规范的稳定执行者”。
答案是 Skill。
2. AI 做性能测试的三个典型误区
先泼三盆冷水。这三个误区我在实际项目里几乎每轮都能看到,看完你就能理解为什么“直接用 AI 裸跑性能测试”会翻车。
2.1 误区一:AI 生成脚本等于完成性能测试
我见过一个很典型的失败案例。某团队把新上的支付回调接口交给 AI,AI 三分钟生成了一份包含 ThreadGroup、HTTP Request、聚合报告的 JMeter 脚本。团队拿着脚本直接跑,发现响应时间 P95 只有 50ms,感觉性能很好,就放心上线了。结果上线两周后,支付高峰时段接口超时告警不断。
问题出在脚本本身。AI 生成的脚本里压根没有参数化,所有并发请求都带着同一个回调订单号,服务端对这笔订单做了缓存,自然测不出真实压力。更麻烦的是,脚本里没有加任何断言,即使接口返回了 500 错误,JMeter 也会把它统计为成功请求。
这就是把“生成脚本”误当成了“完成测试”。性能测试是一条完整链路,生成脚本只是第一环,后面还有参数化、断言、执行、数据收集、指标分析、瓶颈定位。任何一环缺失,前面生成得再漂亮都没有意义。
2.2 误区二:AI 给的并发数、持续时长就是压测需求
很多同学让 AI 生成脚本时会直接说:“给我写一个压力测试脚本,1000 并发,持续 10 分钟。”但压测需求不是这样拍脑袋定的。
1000 并发是什么业务含义?如果是双十一峰值,那要结合历史峰值流量做等比放大;如果是日常稳定性验证,可能 200 并发就够了。持续 10 分钟是稳定性验证还是峰值压测?如果只测 10 分钟,很多内存泄漏、连接池耗尽的问题根本不会暴露。
AI 没有业务上下文,只能给你默认参数。如果你自己不判断,就等于把最重要的压测设计决策交给了随机数生成器。正确的做法是:先由人定义清楚压测目标和场景模型,再由 AI 基于这些约束去生成脚本。约束是人的,执行是 AI 的。
2.3 误区三:AI 说“性能良好”就真的良好
更危险的误区在后面。当你把压测结果贴给 AI,问“这个结果有问题吗?”,AI 很可能会根据平均响应时间和成功率,给出一个“系统整体运行稳定,性能表现良好”的结论。
但性能测试结论不能只看平均值。一个接口,如果 90% 请求是 20ms,10% 请求是 2 秒,平均响应时间可能是 218ms,看起来很好。但 P99 已经烂到没法用,真实用户体验已经拉了胯。AI 不知道你们业务对 P99 的容忍线是多少,不知道数据库连接池的上限是多少,不知道网关是否有超时重试,它在没有上下文约束的情况下给出的分析,最多只能算“数据朗读”,不能算“性能诊断”。
理解了这三个误区,你就明白核心问题不是 AI 本身,而是缺少控制。Skill 就是这个控制层。
3. 核心概念:Skill、Agent 与 Prompt 的本质区别
既然要从 Skill 驱动出发,先把概念讲清楚。最近“Skill”在 AI Agent 和编程助手领域出现频率很高,比如 Codex Skill、各种 Skill 插件,说明它正在成为一个通用范式。但很多人还是分不清 Prompt、Agent、Skill 三者到底有什么关系。
3.1 三者到底有什么不同
用一句话概括:
- Prompt是一次任务的具体指令,每次对话都可能不同。
- Agent是能根据目标自主规划、调用工具并执行任务的 AI 运行体。
- Skill是注入给 Agent 的一组可复用能力包,里面包含领域知识、执行规则、输入输出模板和验证清单。
用打篮球来类比,Prompt 是“这次进攻怎么打”,Agent 是球场上的球员,Skill 是一套训练体系。球员强不强,不只看临场发挥,更看训练体系有没有把投篮、跑位、防守都标准化。AI 做性能测试时,Skill 就是那套训练体系。
3.2 Skill 在性能测试场景中有什么用
具体到性能测试,一个 Skill 至少应该包含四类信息:
| Skill 组成部分 | 解决什么问题 | 示例 |
|---|---|---|
| 领域知识 | 让 AI 理解性能测试基本概念 | 什么是 ThreadGroup、Ramp-Up、聚合报告、P95 |
| 执行规则 | 约束 AI 不能自由发挥 | 必须参数化、禁止写死 Token、必须带断言 |
| 输入模板 | 规范需求描述格式 | 接口地址、请求方式、并发模型、数据准备方式 |
| 验证清单 | 脚本生成后的质量检查 | 校验 JMX 是否包含断言、CSV 参数化路径是否正确 |
当一个 Skill 被定义好后,你不再需要每次都从头教 AI“参数化是什么、断言怎么写”。你只需要把 Skill 文件和当前接口的需求描述一起交给 AI,AI 就会在固定的规则框架下工作。即使换一个团队新人来操作,只要他按流程调用 Skill,产出的脚本质量也能保持在一个稳定的基准线上。
4. 搭建 Skill 驱动性能测试的最小工程骨架
理论说完了,先搭建一个最小可用的工程骨架。这个结构不复杂,但它定义了“谁负责什么”,让 Skill、脚本、结果、分析彼此分开。以后所有压测项目都按这套结构复用。
perf-skill-project/ ├── skills/ │ ├── jmeter-skill.md # AI 生成脚本时要遵守的规则包 │ ├── result-analysis-skill.md # AI 分析结果时使用的知识包 │ └── prompt-templates/ │ └── order-query-scenario.md # 具体的压测需求描述模板 ├── scripts/ │ ├── order_query.jmx # AI 生成的 JMeter 脚本 │ ├── validate_jmx.py # 脚本静态校验工具 │ └── analyze_jtl.py # 压测结果解析工具 ├── data/ │ └── order_ids.csv # 参数化数据文件 ├── results/ │ ├── order_query.jtl # 原始压测日志 │ └── html_report/ # JMeter 生成的 HTML 报告 └── README.md这个结构有三个优点:
- Skill 和业务场景解耦。
jmeter-skill.md放的是团队通用的脚本生成规范,任何接口都能复用;order-query-scenario.md放的是本次压测的接口信息,一个项目一份。 - 脚本、结果、数据分开。生成的脚本放
scripts,参数化数据放data,压测结果放results。这样可以避免把一次性压测数据夹杂到代码库的正式版本里。 - 校验和分析工具独立存在。工具脚本不属于某个业务,可以累积为一个性能测试工具库。
下面重点看jmeter-skill.md这个文件怎么写。这是整个 Skill 驱动方案的核心。
5. 完整示例:从接口文档到 JMeter 脚本
这一节走一个真实的最小闭环。假设要压测一个订单查询接口,业务需求如下:
接口说明: - 接口路径:GET /order/query - 必要请求头:Content-Type、Authorization - 请求参数:orderId(订单号)、userId(用户ID) - 响应校验:HTTP 状态码 200,且返回 JSON 中包含 "success":"true" 压测目标: - 峰值并发:300 虚拟用户 - Ramp-Up 时间:30 秒 - 持续时长:5 分钟 参数化要求: - orderId 从 data/order_ids.csv 读取,不允许所有请求用同一笔订单 - token 必须使用变量占位,不允许写死 断言要求: - 响应状态码必须是 200 - JSON 响应体必须包含 success=true这份需求描述看起来简单,但它已经把最重要的压测设计决策定义清楚了。接下来要让 AI 严格遵守。我们需要先把这些要求转换成 Skill 规则。
5.1 定义 Skill 规则文件
将下面的内容保存为skills/jmeter-skill.md。这份文件既是给 AI 看的规范,也是团队内部的知识沉淀。
# Skill: JMeter 性能测试脚本生成规范 ## 适用场景 任何基于 JMeter 的 HTTP 接口压测脚本生成任务。 ## 输入要求 执行本 Skill 时,用户必须提供以下信息: 1. 接口路径、请求方法、请求头 2. 请求参数及其来源(固定值 / CSV / 随机生成) 3. 并发数、Ramp-Up 时间、持续时长 4. 断言条件(状态码、响应内容、响应时间) 5. 压测环境地址 ## 脚本生成规则 1. ThreadGroup 参数必须使用 __P 函数,便于命令行覆盖: - 并发数: ${__P(users, 300)} - Ramp-Up: ${__P(ramp, 30)} - 持续时长: ${__P(duration, 300)} 2. 必须添加 HTTP Header Manager,包含 Content-Type 和 Authorization 变量。 3. 必须使用 CSV Data Set Config 做参数化,文件路径使用统一占位符。 4. 必须添加 Response Assertion,校验 HTTP 状态码。 5. 必须添加 JSON Assertion 或响应文本断言,校验业务返回码。 6. 禁止在脚本中写死 Token、用户密码、生产环境地址。 7. 必须添加聚合报告 Listener,文件名使用 ${__time(yyyyMMddHHmmss)} 便于区分。 ## 输出规范 返回一个完整可保存的 .jmx 文件,并附上: - 脚本中需要人工确认的参数清单 - 建议采用的 JMeter 命令行执行方式这文件的价值在于,AI 每次生成脚本前都会被强制要求提供完整输入信息。一旦某个字段缺失,它会主动追问,而不是默默用一个默认值补上。
5.2 让 AI 基于 Skill 生成脚本
把jmeter-skill.md和 5.1 的需求描述一起发给 AI,要求 AI 严格按 Skill 生成脚本。一个符合规则的 JMX 核心结构大致如下(为了便于阅读,省略了 JMeter 保存文件时的大量 GUI 属性节点,真实运行时仍建议使用 JMeter 中导出的完整版本):
<?xml version="1.0" encoding="UTF-8"?> <jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="订单查询接口压测"> </TestPlan> <hashTree> <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="订单查询压力组"> <stringProp name="ThreadGroup.num_threads">${__P(users, 300)}</stringProp> <stringProp name="ThreadGroup.ramp_time">${__P(ramp, 30)}</stringProp> <boolProp name="ThreadGroup.scheduler">true</boolProp> <stringProp name="ThreadGroup.duration">${__P(duration, 300)}</stringProp> </ThreadGroup> <hashTree> <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="GET 订单查询"> <stringProp name="HTTPSampler.domain">${__P(baseHost, test.api.example.com)}</stringProp> <stringProp name="HTTPSampler.port">${__P(basePort, 8080)}</stringProp> <stringProp name="HTTPSampler.path">/order/query</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> </HTTPSamplerProxy> <hashTree> <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="请求头管理器"> <collectionProp name="HeaderManager.headers"> <elementProp name="Content-Type" elementType="Header"> <stringProp name="Header.name">Content-Type</stringProp> <stringProp name="Header.value">application/json</stringProp> </elementProp> <elementProp name="Authorization" elementType="Header"> <stringProp name="Header.name">Authorization</stringProp> <stringProp name="Header.value">Bearer ${token}</stringProp> </elementProp> </collectionProp> </HeaderManager> </hashTree> </hashTree> </hashTree> </hashTree> </jmeterTestPlan>这份代码块里的关键设计是:
- 所有压测参数都用
${__P(name, default)}读取,这样后续执行时可以用命令行-J动态覆盖,不需要改脚本文件。 - 域名和端口也做成变量,默认指向测试环境,绝不允许写死生产地址。
- Token 统一使用
${token}占位,具体值从 CSV 或环境参数中获取。
但这只是 AI 生成的“理论脚本”,必须做校验。我见过太多 AI 生成的脚本里 ThreadGroup 的 duration 属性值写错位置,导致调度器不生效。所以脚本校验这一步不能省。
5.3 脚本静态校验工具
把下面的 Python 文件保存为scripts/validate_jmx.py。它不依赖 JMeter,只需要 Python 3,专门用来检查 AI 生成的脚本是否存在低级问题。
# 文件路径:scripts/validate_jmx.py import sys import re def validate_jmx(path: str) -> bool: with open(path, encoding="utf-8") as f: content = f.read() checks = { "存在 ThreadGroup": "ThreadGroup" in content, "并发数使用 __P 参数": "__P(users" in content, "Ramp-Up 使用 __P 参数": "__P(ramp" in content, "持续时间使用 __P 参数": "__P(duration" in content, "存在 HeaderManager": "HeaderManager" in content, "存在 Host 变量": "__P(baseHost" in content, "客户端地址未写死": "test.api.example.com" not in content.replace("__P(baseHost", ""), "Token 未被写死": re.search(r"Bearer\s+[a-zA-Z0-9]{20,}", content) is None, } passed = True for name, ok in checks.items(): print(f"[{'PASS' if ok else 'FAIL'}] {name}") if not ok: passed = False return passed if __name__ == "__main__": if len(sys.argv) != 2: print("用法: python validate_jmx.py <jmx文件路径>") sys.exit(1) ok = validate_jmx(sys.argv[1]) sys.exit(0 if ok else 1)运行方式:
python scripts/validate_jmx.py scripts/order_query.jmx当脚本里出现写死的 Token 或者没有参数化时,这个校验工具会直接打印 FAIL。它会拦住 AI 最常见的三个低级错误:没有参数化、没有断言、写死了敏感信息。
不过要说明一点,这个工具做的是“静态规则校验”,它只能保证脚本结构上没有明显问题,不能替代真实压测环境中的小并发冒烟。脚本校验通过后,下一步才是真正执行。
6. 全链路执行与结果分析
脚本通过校验后,开始正式压测。这里的关键是一开始就用命令行模式执行,不要用 JMeter GUI 跑并发,GUI 本身会消耗本地资源,影响测试数据准确性。
6.1 压测执行命令
准备好参数化数据data/order_ids.csv,然后执行:
jmeter -n -t scripts/order_query.jmx \ -Jusers=300 \ -Jramp=30 \ -Jduration=300 \ -JbaseHost=test.api.example.com \ -JbasePort=8080 \ -Jjmeter.save.saveservice.output_format=csv \ -l results/order_query.jtl \ -e -o results/html_report参数解释:
| 参数 | 含义 |
|---|---|
-n | 非 GUI 模式执行 |
-t | 指定 JMX 脚本路径 |
-Jusers=300 | 覆盖 ThreadGroup 的并发数 |
-Jramp=30 | 覆盖 Ramp-Up 时间 |
-Jduration=300 | 覆盖持续时间,单位秒 |
-l | 原始结果日志输出路径 |
-e -o | 生成 HTML 可视化报告 |
执行结束后,JMeter 会在results/html_report下生成聚合报告页面,在results/order_query.jtl下生成原始日志。先打开 HTML 报告看全局,再看 JTL 做更细的分析。
6.2 JTL 结果解析
JMeter 的 HTML 报告有基础信息,但做瓶颈分析时不够灵活。我建议写一个小脚本直接解析 JTL。将下面的代码保存为scripts/analyze_jtl.py:
# 文件路径:scripts/analyze_jtl.py import csv import sys from collections import defaultdict def load_samples(jtl_path: str): samples = [] with open(jtl_path, newline="", encoding="utf-8") as f: reader = csv.DictReader(f) for row in reader: if not row.get("timeStamp"): continue samples.append({ "timestamp": int(row["timeStamp"]), "elapsed": int(row["elapsed"]), "success": row["success"] == "true", "response_code": row.get("responseCode", ""), "thread_name": row.get("threadName", ""), }) return samples def percentile(sorted_list, percent): if not sorted_list: return 0 index = int(len(sorted_list) * percent) - 1 index = max(0, min(index, len(sorted_list) - 1)) return sorted_list[index] def analyze(samples): total = len(samples) errors = [s for s in samples if not s["success"]] success = [s for s in samples if s["success"]] elapsed_sorted = sorted(s["elapsed"] for s in samples) success_elapsed_sorted = sorted(s["elapsed"] for s in success) duration_sec = (samples[-1]["timestamp"] - samples[0]["timestamp"]) / 1000 tps = total / duration_sec if duration_sec > 0 else 0 print(f"样本总数: {total}") print(f"错误请求数: {len(errors)} ({len(errors) / total * 100:.2f}%)") print(f"平均响应时间: {sum(s['elapsed'] for s in samples) / total:.2f} ms") print(f"成功请求平均响应时间: {sum(s['elapsed'] for s in success) / len(success):.2f} ms" if success else "无成功请求") print(f"P90: {percentile(elapsed_sorted, 0.90)} ms") print(f"P95: {percentile(elapsed_sorted, 0.95)} ms") print(f"P99: {percentile(elapsed_sorted, 0.99)} ms") print(f"TPS: {tps:.2f}") print(f"错误码 Top5: {defaultdict(int, {e['response_code']: defaultdict(int, {})}) if False else ''}") code_counter = defaultdict(int) for s in errors: code_counter[s["response_code"]] += 1 for code, count in code_counter.most_common(5): print(f" HTTP {code}: {count}") if __name__ == "__main__": if len(sys.argv) != 2: print("用法: python analyze_jtl.py <jtl文件路径>") sys.exit(1) samples = load_samples(sys.argv[1]) if not samples: print("未解析到样本数据,请确认 JTL 是 CSV 格式") sys.exit(1) analyze(samples)运行:
python scripts/analyze_jtl.py results/order_query.jtl输出示例(实际值取决于压测环境和数据):
样本总数: 218735 错误请求数: 0 (0.00%) 平均响应时间: 142.31 ms 成功请求平均响应时间: 142.31 ms P90: 210 ms P95: 256 ms P99: 498 ms TPS: 729.78拿到这组数据后,性能测试的全链路还没结束,因为数据不等于结论。比如 P99 是 498ms,到底算不算达标,取决于业务方给出的 SLA 指标。如果 SLA 是 P99 小于 300ms,那这个接口就是不合格的,需要进入瓶颈定位环节。
6.3 瓶颈定位的基本路径
JTL 数据只告诉你“哪里慢”,不告诉你“为什么慢”。定位瓶颈时建议按下述顺序展开:
- 先看导出的 HTML 报告中的 TPS 趋势图。如果 TPS 在压测中途出现明显下降,大概率是线程池或连接池被打满。
- 再用
jstack采集压测期间 Java 服务的线程快照,看是否有大量线程阻塞在 JDBC 连接获取或远程调用上。 - 接着查数据库慢日志。如果响应时间随并发上升而明显上升,且 TPS 上不去,通常不是接口代码问题,而是数据库 SQL 或锁等待问题。
- 最后看中间件指标,包括 Redis 命中率、MQ 堆积量、Nginx 连接数。很多性能瓶颈发生在中间链路而不是应用本身。
这一步是纯人工经验,AI 目前无法替代你做出“先看连接池还是先看慢 SQL”的决策。但它可以帮你把每个环节要看的指标整理成检查清单,减少漏查。
7. 常见问题与排查方法
AI 参与性能测试后,常见问题其实集中在脚本生成和结果解释两个阶段。下面按实际出现频率整理:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| AI 生成的脚本没有任何参数化 | Prompt 未要求,AI 默认使用固定值压测 | 检查 HTTP Sampler 的请求参数是否引用 CSV 或变量 | 在 Skill 中加入“必须参数化”的硬性规则 |
| 脚本中的 Token 被写死 | AI 不知道 Token 需要动态获取 | 在 JMX 中搜索Bearer后的长字符串 | 改为${token}变量,并在 Skill 中禁止写死密钥 |
| 线程组调度器不生效,压测时间失控 | Duration 属性被 AI 写错在节点 | 打开 JMX 查看 ThreadGroup 下 scheduler 属性 | 用validate_jmx.py做静态校验 |
| 压测结果成功率高但实际业务报错 | 只加了 HTTP 状态码断言,没做业务返回断言 | 查看 JTL 的响应数据,确认响应体内容 | 增加 JSON Assertion,校验业务返回码 |
| AI 分析报告时说“性能良好”但 P99 很烂 | AI 只看平均响应时间,缺少分位数概念 | 把 P95/P99 指标和 SLA 写入 Skill 规则 | 在结果分析 Skill 中规定必须输出分位数和成功数分布 |
这里真正容易踩坑的是第二个问题。很多团队让 AI 生成脚本后,根本没检查过 Token 是不是被写死了。如果压测脚本里的 Token 是部署环境的真实密钥,压测日志一旦泄露,风险非常大。所以在 Skill 规则中明确“禁止 AI 在脚本中生成任何敏感常量字符串”,并在校验工具中持久化执行,是最值得投入的自动化防线。
8. 最佳实践与工程建议
Skill 驱动性能测试跑通之后,下一步是把它做成团队的标准工程能力。以下建议来自实际项目落地时的经验,直接复制可以少踩很多坑。
8.1 先把一条链路跑通,再横向扩展
不要一开始就想把全公司的接口都纳入 Skill 体系。先选一个简单的读接口,比如订单查询、商品详情,把从需求到出报告的链路跑通,确认脚本可靠、分析工具顺手。之后再扩展到写接口、消息消费场景、数据库脚本。一套连一条链路都没跑通的体系,只是一个空壳。
8.2 Skill 文件必须纳入版本管理
Skill 文件不是临时提示词,它是团队的技术资产。建议像管理代码一样管理skills/目录,每次修改都要提交 commit,并注明修改原因。例如“在 Skill 里增加禁止写死 Token 的规则”,这条 commit 记录会让后来的人知道为什么要加这条约束。没有版本管理的 Skill 会退化成一段没人维护的旧文本。
8.3 参数化数据要贴近真实分布
压测数据的质量直接影响测试结论。条件允许时,从生产环境采样一批真实请求参数,做脱敏处理后保存为 CSV。这样做的好处是请求参数的长度、分布、重复比例更接近真实流量,测试结果更可信。如果只能用构造数据,要注意避免所有参数过长或过短、字段为空的极端情况,否则压测容易得出偏差较大的结论。
8.4 小并发冒烟是必经环节
直接拿 300 并发打集群之前,先跑一轮 5 个用户、持续 30 秒的小并发冒烟。这轮测试的目的是验证脚本本身没有问题,而不是压测服务性能。很多脚本问题(参数化路径错误、断言表达式写错)在低并发下就能暴露,没有必要浪费一次完整压测的时间去发现。
8.5 生产环境压测必须审批
这里要特别强调安全边界。性能测试尤其是在生产环境执行时,必须获得系统负责人和业务方的明确授权,提前约定压测时间窗口和回滚预案。Skill 中应增加一项规则:默认压测目标是测试环境,若要压生产,必须在执行前检查审批记录。这不是形式主义,是保护好自己和团队的基本职业底线。
8.6 人工评审 AI 产出的脚本
AI 生成的脚本通过静态校验后,最好安排一个有经验的测试工程师做一次快速评审。评审重点不是看代码是不是符合 JMeter 语法,而是看业务含义是否和需求一致:压测目标真的反映业务峰值吗?断言真的覆盖了业务返回吗?参数化数据真的模拟了真实请求吗?AI 是执行者,我们才是负责人。
9. 总结与后续学习方向
这篇文章想表达的核心判断很简单:AI 做性能测试,真正的价值不在“帮你写一段脚本”,而在“帮你把脚本生成和结果分析的工程约束稳定地执行出去”。Skill 就是实现这件事的载体。它把散落在个人经验里的规则固化下来,让 AI 在约束下工作,让团队新人也能按照同样的路径产出合格的结果。
看完这篇文章,建议你沿着下面的顺序实践:
- 新建一个
perf-skill-project目录。 - 把文中给的
jmeter-skill.md、validate_jmx.py、analyze_jtl.py复制进去。 - 找一个只读接口,把接口文档整理成标准需求描述。
- 让 AI 基于 Skill 生成脚本,用校验工具检查,再用小并发冒烟。
- 完整跑一轮压测,解析 JTL,形成自己的性能基线数据。
后续可以深入的方向包括:把 Skill 接入到 CI 流水线,让每次代码变更后自动触发回归压测;把多个 Skill 组合成一个 Agent 工作流,实现从提需求到出报告的半自动化;把结果分析 Skill 做得更细致一些,让 AI 根据 TPS、响应时间分布、错误码比例自动生成初步诊断建议。
性能测试是个越做越有积累的领域,AI 不会取代性能测试工程师的判断,但它能把我们从重复劳动里解放出来。只要把规则先定好,AI 就能成为团队里干活最稳的搭档。