ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Web性能测试入门:并发用户、TPS、响应时间与压测避坑

Web性能测试入门:并发用户、TPS、响应时间与压测避坑

简介:《Web性能测试--基础概念》是一份面向初级性能测试学习者的PDF讲义,围绕Web应用在高负载下的响应时间、吞吐量与并发处理能力展开,帮助刚接触性能测试的读者建立概念框架并理解测试实施的整体流程。内容由虫师讲解,先梳理压力测试、负载测试、稳定性测试与竞态条件测试等分类,再解释并发用户、理发店模式、吞吐量和响应时间等核心指标;随后按问清性能测试需求、了解系统架构、分析测试点、工具选型、编写测试计划、环境搭建、测试实施、性能调优到输出报告的路径展开,适合用作入门自学或团队内部分享的提纲。压缩包共1个PDF文件,大小约531KB,轻量便于查阅。已有465人学习,读者可从中获得基础概念梳理、指标理解与完整测试流程框架,为后续工具实践和性能调优打下基础。

1. 一份讲概念的 PDF,凭什么叫压测的第一份读物

接手 Web 性能测试任务的第一天,多数人是先打开工具而不是先打开文档:拉 200 个线程跑十分钟,看一眼平均响应时间 300ms,交差。等到评审会上被问“这 200 并发怎么算出来的”“TPS 到 800 之后为什么不涨了”,往往就接不上话。这份 Web 性能测试基础概念讲义处理的正是这段接不上话的空白——它不讲某个工具怎么点按钮,而是先把并发用户、吞吐量、响应时间这几个基础概念的界定说清楚,再给出从需求澄清、架构梳理、测试点筛选、工具选型、计划编写、环境搭建、实施到性能调优的完整链路。它适合刚接触性能测试、手里有压测任务但说不清指标口径的人,也适合做了几年、报告里还在只写平均值的人回头对一遍尺子。

2. 七种测试分类:用爆发力、耐力、协调性判断该做哪一种

2.1 七个名词的边界,先分清再动手

同一句“做个性能测试”,五个人的理解可能是五种:有人想验证上线前能不能扛住,有人想找崩溃点,有人想复现死锁,有人想调 JVM 参数,还有人只想出一份报告。讲义把常见的七类摊开讲,从施压方式、关注点、产出物三个维度切开,这是全篇最有价值的一页纸。

类型施压方式要回答的问题主要观测项典型产出
狭义性能测试按生产业务量恒定施压是否达到宣称的能力指标响应时间、TPS达标/不达标结论
负载测试阶梯递增直到指标越界容量拐点在哪里TPS 曲线、资源曲线容量结论
压力测试阶跃到饱和后保持极限状态下会不会出错错误率、资源饱和、恢复情况崩溃点与稳定性结论
并发测试同一时点打同一操作有没有死锁、线程锁、资源争用错误类型、锁等待、线程栈并发缺陷清单
配置测试变更软硬件配置做对比哪个因素对性能影响最大同场景多组对比数据调优优先级
可靠性测试中等压力长时间跑能不能长期稳定运行内存增长、句柄、GC、错误率耐久性结论
失效性测试局部故障注入局部挂了其它模块是否可用故障影响范围容错结论

这七类真正的差别不在名字,在“加压函数”和“终止条件”。狭义性能测试的加压是平的,终止条件是跑完预定轮次;负载测试的加压是阶梯上升的,终止条件是某项指标越界;压力测试的加压是阶跃到饱和后保持,终止条件是时长到了或者系统崩了;并发测试在加压函数上可能只需要很小的量,但要求所有虚拟用户在同一时刻命中同一个操作。把加压方式和终止条件写清楚,分类就不会混,测试计划的验收条款也才有依据。

讲义里还有一个诚实的判断:这些名词连不少专业测试人员都分不清,因为资料给的解释都停留在“从不同角度和关注点解释”,并没有给出本质区别。所以别在命名上纠结,直接问自己一句——这次压测结束之后,我要拿哪一句话去汇报?那句话就是测试类型。

2.2 爆发力、耐力、协调性:七类收敛成三类动作

讲义用运动员做类比,这个类比比任何分类表都好记。举重选手的考核只有一件事:你能举起多大的重量,举起来三秒就算成功,对应系统的爆发力,也就是能承受的最大压力。马拉松选手的百米速度没用,四十公里谁先到终点才是赢家,对应系统的耐力,也就是长时间处于压力下的稳定性。教练看运动员还有第三件事——整体协调性,看哪块是短板:一个运动员各部位都练得强壮,但右臂先天性萎缩,成绩也许还行,可跑起来全身都在替右臂代偿,这个短板决定了体能上限,对应到系统就是瓶颈定位与调优。

考核维度系统侧问题对应测试类型判据
爆发力最大能扛多少并发、多少 TPS负载测试、压力测试TPS 拐点、错误率突增点
耐力长时间跑会不会内存泄漏、句柄耗尽可靠性测试连续运行后资源曲线是否单调上升
协调性哪个环节是瓶颈、调哪个参数收益最大配置测试、并发测试同场景多组对比,收益排序

落到实操,一次完整的压测很少只做一种。常见组合是“负载找容量 → 压力看稳定性 → 配置测试做调优”:先用阶梯负载找到 TPS 不再增长的那个并发量,再用这个量附近的值做几小时可靠性验证看内存和句柄曲线,最后针对暴露出来最严重的资源做配置对比,一次只改一个变量。

这里有个容易被忽略的反直觉点:同一条错误日志,在不同测试目标下结论相反。压力测试跑到一半系统报 OOM,如果目的是找崩溃点,那 OOM 就是结果;如果目的是稳定性验证,那 OOM 就是缺陷。所以计划里必须先写目的,再写判据,顺序反了,后面所有数据分析都会来回摇摆。

2.3 需求四问与场景卡:把分类落到可执行的计划里

讲义把性能测试目的归成四类,每一类的工作重点完全不同:

1)新系统能力验证。上线前验证,环境和压力点可以自由选,工具也灵活,如果没有明显短板,不需要调优,工作量最小。

2)客户有明确要求。比如“系统要同时满足 100 用户登录,平均每个用户登录时间不超过 5 秒”,这种最好办,因为判据现成。但要注意需求方可能提不现实的数字,先做一次可行性折算再承诺。

3)找出系统性能瓶颈。重点在架构分析和业务分析,不在压测执行本身,压测只是取证手段。

4)稳定性验证。重点在运行时长和观测项,压力反而不宜拉满。

问目的还有一层隐性收益:从对方的措辞里能判断这次任务在项目里的优先级,决定你投入多少时间去搭环境、做数据准备。

目的定完,接着筛测试点,讲义给了三条标准:发生频率非常高的(某些核心业务占每天业务总量 90% 以上)、关键程度非常高的(绝对不能出问题的模块)、资源占用非常严重的(一次提交要写数十张表,或一次查询要检索大量记录)。三条里命中两条就优先测,全不命中的先放后面。

需求描述还要满足三个要求:准确、一致、特定。准确指带有数字和条件,比如“系统必须在不超过 10 秒的响应时间内处理 20 起登录任务”。一致指用户和测试人员对术语的理解必须对齐——并发用户数、在线用户数、注册用户数这三个词一旦混用,整场测试的结论就作废。特定指需求一定有前提条件,比如“后台关键业务数据 10G、操作数据量 20K、1500 个用户、500 并发、连续运行 12 小时”。

把这些落成一张场景卡,比写三页文档管用:

# 场景卡:登录(示例,字段按项目实际改) scene: login # 场景名,和监控面板、报告标题保持一一对应 goal: capacity # capacity 找容量 / stability 稳定性 / bottleneck 找瓶颈 load_model: type: stair # flat 恒定 / stair 阶梯 / spike 突刺 start_users: 50 step_users: 50 step_hold: 300 # 每档保持 300 秒,等 TPS 与响应时间进入平台期 max_users: 800 sla: avg_rt_ms: 2000 # 平均响应时间上限 p95_rt_ms: 5000 # 95 分位,防止长尾被平均掉 error_rate: 0.001 # 错误率上限 0.1% min_tps: 300 # 由业务量倒推的下限,不是拍脑袋 duration_min: 30 observe: [tps, rt, error_rate, cpu, gc, db_qps, conn_pool]

参数说明:step_hold别设太短,一档只跑 30 秒,TPS 还在爬坡就读数,会把容量算小;p95_rt_ms是必须项,只看平均会被少数慢请求掩盖;min_tps一定要从业务量倒推,而不是看压测结果反填,否则就变成“系统能跑多少我们就要求多少”。observe里预留了 GC 和连接池,是因为这两项在压测中一旦异常,响应时间的分布会明显变形。

3. 并发用户与理发店模型:把在线人数折算成压测目标值

3.1 三种并发口径:用户视角和服务器视角不是一回事

并发有两种情况。严格意义上的并发,是所有用户在同一时间点做同一件事,比如同一时刻并发登录、同一时刻提交表单。广义的并发,是多个用户在同一时刻发出请求,但请求内容可以不同——有人在登录,有人在提交表单。

这两种都是用户业务视角的口径,因为日常压测就是从用户端对业务层操作来施压的。但从服务器角度看,情况是另一回事:把系统运行过程切成离散时间点,每个点上都有一个“同时向服务端发送请求的用户数”,这才是服务器承受的并发访问数。

讲义里有个判断值得记住:真正意义上的并发并不存在。压测工具一秒能造出成千上万个请求,但这些请求的产生本身有先后顺序;即使真的“同时”产生,经过网络传输时受带宽和延迟影响,到达服务器时也已经不同步了;服务器收到并发请求后处理也要排队,只是每个请求处理时间极短,单核每秒能处理几千几万次,所以更准确的说法是“并发能力是每秒多少次”。

由此引出三个必须分清的词:

概念含义典型来源
系统用户数有权限使用系统的注册用户总量用户表总量
同时在线人数同一时刻打开着系统的用户数在线统计、会话数峰值
并发用户数同一时刻真正发出请求、给服务器造成压力的用户数服务器日志分析 + 业务建模

讲义的例子很直白:某站 20 万注册用户,在线统计峰值 2 万人,能说并发用户数是 2 万吗?不能。2 万人里大部分只是把页面开着,不产生请求,实际并发数取决于业务访问模式,通常要靠服务器日志分析得到。这个折算如果做错,后面所有的压测目标都是错的。

3.2 理发店模型:最佳用户数 3 和最大用户数 9 是怎么来的

前提三条:店里有三位师傅,每位师傅服务一位顾客需要一小时,顾客最多只能等待三小时(等待时间加被服务时间)。

最佳用户数:师傅不休息、顾客也不用等,三个人进来三个人开剪。所以最佳用户数是 3。

最大用户数:早上一开门来了一大群顾客。A、B、C 先剪;D、E、F 要等一小时才轮得到;G、H、I 要等两小时;再往后的顾客已经等了三小时还没轮到,达到忍耐极限,走了。所以任一时刻店里能服务的最大用户数是 9。

店内位置人数状态
理发椅上3正在被服务
等待区第一批3刚等 0 小时,还需 1 小时
等待区第二批3已等 1 小时,还需 2 小时
门口若干已等 2 小时,再等就触顶,转身离开

还有两个容易漏的边界:一是那些等了三小时没等到而离开的顾客,不能计入最大用户数;二是店面本身有容量上限,如果店很小最多容纳六个人,第七个人即使只要等两小时就能被服务,也进不来。这两个边界对应到系统上,就是超时阈值和队列长度上限。

映射到系统:

理发店系统
3 张理发椅工作线程数、连接池上限
每位 1 小时单个请求的处理耗时
最多等 3 小时请求超时、排队超时阈值
店内容量上限队列长度、最大连接数
最佳用户数 3不排队前提下的并发处理能力
最大用户数 9允许排队但不超时的并发承接上限

压测目标一般落在最佳用户数和最大用户数之间,具体位置看 SLA 允许多长等待。如果业务要求“用户点一下就得马上有反应”,目标趋近最佳用户数;如果业务允许排队,可以往最大用户数靠,但必须接受响应时间线性上升。

这里有个夺回主动权的细节:大量超时错误出现时,先看是“处理慢导致排队超时”还是“系统已经处理不了”。前者表现为 TPS 稳、响应时间涨、少量超时;后者表现为 TPS 掉、错误率飙升、资源打满。两者处理方式完全不同,一个是缩队列或加超时,一个是加资源或改代码。

3.3 从访问日志把在线数折算成并发数

从日志出发是最靠谱的路子。先把日志按秒聚合,看每秒请求数的峰值和平均值:

# 统计 access.log 每秒请求数峰值 # 假设是 combined 格式:$1 是 IP,$4 形如 [10/Oct/2023:13:55:36 awk '{ ts = substr($4, 2, 20) # 取到秒级时间戳,去掉开头的 [ cnt[ts]++ # 按秒计数 } END { for (t in cnt) { if (cnt[t] > max) { max = cnt[t]; max_ts = t } sum += cnt[t]; n++ } printf "peak_qps=%d at %s\n", max, max_ts printf "avg_qps=%.1f over %d seconds\n", sum/n, n }' access.log

参数说明:$4是 combined 日志格式里带方括号的时间字段,日志格式不一样要换列号,先head -1看一眼;substr($4,2,20)取 20 个字符,因为[10/Oct/2023:13:55:36正好是 20 个字符。统计窗口建议取业务高峰那一段,不要用全天平均,全天平均会把峰值抹平一半以上。

有了 QPS,再用利特尔法则折平均并发:

# 平均并发 ≈ 到达率(请求/秒) × 平均停留时间(秒) # 停留时间用服务端处理耗时,不含浏览器呈现与公网传输 peak_qps = 850 # 上一步统计出的峰值 QPS avg_rt_ms = 120 # 同一时段的平均处理耗时 think_time_s = 0 # 算容量时先按 0,模拟真实用户行为时再按日志间隔设 avg_rt_s = avg_rt_ms / 1000 concurrency = peak_qps * (avg_rt_s + think_time_s) print(f"平均并发 ≈ {concurrency:.0f}") print(f"按 1.5 倍余量,压测并发建议 ≥ {concurrency * 1.5:.0f}")

这个数只反映平均值。如果响应时间分布长尾严重,实际需要的线程数会高于它;另外压测工具的线程数并不等于并发数,线程里有思考时间、有等待,真正的并发数要看 TPS 乘响应时间。所以我一般把算式当起点,不当结论——先用它定一个初始档位,然后阶梯加压看 TPS 在哪里拐弯,以拐点为准。这也解释了为什么第 2 章的负载测试是阶梯模型:算出来的数是假设,压出来的曲线才是事实。

4. 吞吐量、TPS 与响应时间:三个指标的单位陷阱与三段拆解

4.1 吞吐量不是能力,吞吐率才是

吞吐量指在一次性能测试过程中网络上传输的数据量的总和。对交互式应用来说,它反映服务器承受的压力,在容量规划里是重点指标,在调优过程中也有参考价值。

讲义的工厂比喻很到位:一个大型工厂生产效率很高,一天能生产 10 万吨货,结果运输能力只有两辆小三轮,一天拉 2 吨。这个运输能力就是整个系统的瓶颈。所以看吞吐量不能只看产出端,要看链路上最短的那块板。

但直接用吞吐量衡量一个系统的输出能力极其不准确。一个水龙头开 24 小时流出 10 吨水,10 个水龙头开 1 秒流出 0.1 吨水,难道能说一个水龙头的出水能力远超十个?显然不能。所以必须加时间维度,这就引出吞吐率:单位时间内网络上传输的数据量,或单位时间内处理客户请求的数量。

单位怎么选,决定了报告能不能被看懂:

口径单位适用场景注意
字节/秒KB/s、MB/s网络带宽评估、大文件下载类业务受响应体大小影响极大
请求数/秒req/s接口级压测、绝大多数 Web 场景和工具里的 Throughput 对应
页面数/秒page/s整页加载类场景要明确页面是否含静态资源
业务数/小时件/小时、笔/小时审批、计费、订单类系统业务方最容易理解

最常见的错误是把字节/秒和请求数/秒混在一份报告里对比。压测工具给的 Throughput 通常是请求数/秒,网络监控给的是 KB/s,两者的换算关系取决于每次请求的响应体大小,接口返回 2KB 和返回 200KB,同一个 TPS 对应的字节吞吐差 100 倍。报告里要么统一一个口径,要么两个都给并写清换算依据。

4.2 事务、TPS、点击率:把业务翻译成计数单位

事务是用户某一步或几步操作的集合,前提是它要有完整意义:对一个页面的一次请求、对系统的一次登录、对商品的一次确认支付,都可以看作一个事务。事务的定义直接决定 TPS 的分母。

TPS(Transaction Per Second)是每秒系统能处理的事务或交易数量,衡量系统处理能力的重要指标。

点击率(Hit Per Second)是每秒用户向 Web 服务器提交的 HTTP 请求数,可以看作 TPS 的一种特定情况。区别在于:点击率更能体现用户端对服务器的压力,TPS 更能体现服务器对客户请求的处理能力。点击是 Web 应用能处理的交易的最小单位——Web 应用是“请求—响应”模式,用户发一个申请,服务器处理一次。

这里有个必须钉死的边界:一次鼠标“单击”可能触发多个 HTTP 请求。比如一次登录操作,页面本身 1 个 HTML、3 个 JS、2 个 CSS,加上 1 个登录 XHR,一共 7 个请求。如果事务定义成“用户点一次登录按钮”,那 TPS 是 1,HPS 是 7。报告里如果不写清楚事务边界,同一次测试可以被读出两种完全不同的结论。

我的习惯是在场景卡里把事务边界写成一句话,比如“登录事务只包含登录 XHR,不含静态资源”,让后面所有看报告的人不需要再猜。

吞吐量指标到底有什么用,讲义给了两条:

第一,协助设计性能测试场景并衡量是否达到预期。设计场景时,根据估算的吞吐量数据对应到测试场景的事务发生频率、事务发生次数;测试完成后,用实际吞吐量衡量是否达到预期目标。

第二,协助分析性能瓶颈。吞吐量受限是性能瓶颈的一种重要表现形式,有针对性地对吞吐量设计测试,可以尽快定位瓶颈位置。讲义引了一个 RBI(快速瓶颈识别)方法,基于三条事实:发现的 80% 系统性能瓶颈都由吞吐量制约;并发用户数和吞吐量瓶颈之间存在一定关联;采用吞吐量测试可以更快速地定位问题。做法是不断增加并发用户数和吞吐量,观察系统在哪里停止增长,再从网络、数据库、应用服务器和代码本身四个环节确定瓶颈。

4.3 响应时间三段拆解:哪一段你能控制

从用户角度,软件性能就是软件对用户操作的响应时间:从单击开始,到系统把结果以用户能识别的方式展示出来,这段时间就是用户对性能的直观印象。

这个总时间要拆开才有用,讲义拆成三段:

呈现时间,主要是浏览器对接收到的数据的处理和展示。同一台电脑同一个网站,不同浏览器呈现速度有差异,这部分和浏览器、操作系统、本机 CPU 内存都有关。配置很低的机器上多开几个网页就可能卡死,这时候怪系统是不公平的。

数据传输时间,最容易被初学者忽略。寄信给远方的朋友,影响收信时间的不是你写信的时间,也不是对方读信的时间,而是运输的时间。发请求要时间,返回响应也要时间。讲义还点破了一个典型误区:有人喜欢拿压测工具去打互联网上的站点,甚至以为能把别人的站点打挂。先问自己带宽多少,互联网是个网,相同起点终点可能走不同路线,网络延迟摆在那里;就算请求都发出去了,到达目的地时也已经不能叫并发了。所以做服务端能力验证,要在局域网里做。

系统处理时间,系统拿到请求后处理并把结果返回的时间。呈现时间和传输时间都不可控,用户电脑和浏览器千差万别,网络状况千差万别,唯一能控制的是把服务端处理请求的时间压到最短。

据此,压测时的几个标准动作就不难理解了:工具一般屏蔽响应的呈现过程,只模拟多用户并发请求、计算用户得到响应的时间,不把每个响应都渲染给客户端;传输时间在局域网内可忽略不计;思考时间在做容量测试时设 0,做真实业务模拟时按日志统计的用户操作间隔设;带宽模拟除非专门做弱网测试,否则关掉,否则测出来的是网络不是系统。

工具侧的执行命令,常见做法是这样:

# 非 GUI 模式执行,避免压测机自身被 GUI 吃掉资源 jmeter -n -t login_500.jmx -l result_500.jtl -e -o report_500 # 从 jtl 里按秒聚合 TPS 与错误数,快速看曲线形状 # 列顺序以实际表头为准,先 head -1 result_500.jtl 确认 awk -F, 'NR>1 { split($1, a, "."); sec = a[1] # 第 1 列是毫秒时间戳,取到秒 n[sec]++ if ($8 == "false") e[sec]++ # 第 8 列 success,false 表示失败 } END { for (s in n) printf "%s req=%d err=%d tps=%d\n", s, n[s], e[s]+0, n[s] }' result_500.jtl | sort

参数说明:-n非 GUI 模式,-t指定脚本,-l指定结果文件,-e -o生成 HTML 报告目录,目录必须为空。这条聚合命令的价值在于它一秒一秒地还原了 TPS 的形态——平均值看不出拐点,逐秒数据才能看出从第几秒开始 TPS 走平、错误从第几秒开始出现。不同工具导出的 CSV 列顺序不完全一样,用列号之前先看表头,这一步不能省。

还有一个参数层面的经验:响应时间的判据别只写平均值。同一批数据里平均 800ms 可能是“全部 800ms”,也可能是“80% 是 200ms、20% 是 3 秒”,两者的系统健康度天差地别。所以场景卡里的 p95 是必须项,配合错误率一起看。

5. 避坑排查:五个把压测结果做废的常见操作

5.1 压测机自己先成了瓶颈

现象:虚拟用户数加到 300 就上不去了,TPS 卡住不涨,但被测系统的 CPU 只用了 20%。

原因:压力发生器本身被吃满。单台压测机的 CPU、内存、可用端口数、出口带宽都是上限,线程一多,光建立连接就耗掉大半资源,测出来的响应时间里还混着压测机的排队时间。

解决:压测期间同步监控压测机自身的 CPU、网络和端口占用;并发量上去之后改用多台压测机分布式施压;把结果收集和报告生成放到压测结束之后做,别在压测机上同时跑;用非 GUI 模式执行,GUI 模式自身开销很大。判断方法很简单——压测机资源打满而被测机资源空闲,结论一律作废。

5.2 在公网施压,测出来的不是并发

现象:脚本在局域网跑 TPS 有 900,换成访问公网地址只剩 120,响应时间抖动剧烈,错误里大量是连接超时。

原因:公网链路受带宽、路由、延迟影响,请求发出后到达服务端时早已不同步,严格并发根本构不成;抖动带来的长尾会把 TPS 曲线压得看不出形状。

解决:服务端能力验证一律在独立局域网内做,测试机与被测系统在同一网段,网络环境保持独立,压测期间别让其它机器抢路由器和带宽资源。如果确实要评估公网体验,那属于端到端体验测试,关注的是“用户体验到的响应时间”,不能用来反推服务端的处理上限,这两类结论别混在一份报告里。

5.3 把同时在线人数当成了并发用户数

现象:需求方说“我们有 2 万在线用户”,压测直接按 2 万线程开跑,系统瞬间雪崩,团队被要求紧急扩容。

原因:把在线数等同于并发数。在线用户里大部分只是把页面开着,不发请求;真实并发数取决于业务访问模式,要靠日志分析加业务建模折算。

解决:先按第 3 章的方法从日志算出峰值 QPS,再用利特尔法则折平均并发,然后阶梯加压找拐点。和需求方对齐时把三个数字分开写:注册用户数、同时在线人数、并发用户数,各自标注来源和测算方法。这一条不做,后面所有的容量结论都没有意义。

5.4 只看平均值,不看分位和错误率

现象:报告写“平均响应时间 500ms,性能良好”,上线后用户投诉卡顿,回查发现 8% 的请求超过 5 秒。

原因:平均值会把长尾抹平。压测工具默认汇总的是平均响应时间,如果没人主动去看分位分布,慢请求在汇总表里基本隐形。另一个常见错误是把超时当成功——有些工具默认不把超时算失败,错误率看着很低,实际大量请求压根没回来。

解决:报告里固定输出平均、p90、p95、p99 和错误率五项,并明确错误率的统计口径(哪些状态码算失败、超时算不算)。分析时先看错误率再看响应时间:错误率超过阈值,响应时间的数就没有参考价值了,因为成功的样本已经被筛过一遍。

5.5 环境与数据不一致,两轮结果不可比

现象:调优前后各跑一轮,TPS 从 700 涨到 950,但上线后没有明显改善,甚至更慢。

原因:两轮压测的环境或数据不一致——数据量从 10 万涨到 500 万、缓存没预热、连接池参数被人动过、同一台机器上还跑着别的服务。这些变量任何一个变了,两轮结果的差值就不能归因到你要验证的那个改动上。

解决:把测试环境当固定设施管理,压测前确认三件事——数据量级与目标场景一致、服务已预热且缓存状态明确、这轮相比上轮只改了一个变量。讲义在计划部分特别强调性能测试最好在独立环境内进行,理由就是“你压测时其它人也在访问,拿到的数据不是独立的”。这句话在实际项目里被违反的频率高得离谱,血泪经验。

6. 从压测结果到调优闭环:三条曲线和一个判读表

拿到一堆数据之后,真正决定成败的是怎么读。我习惯先把三条曲线画在同一张时间轴上:TPS、响应时间(用 p95 而不是平均)、错误率,再把 CPU、GC、连接池、数据库 QPS 作为辅助曲线叠在下面。读法只有一句:找 TPS 走平的那一秒。

曲线形态判读下一步动作
TPS 线性上升,p95 平稳还没到容量区继续加压,别急着下结论
TPS 走平,p95 开始线性上升容量拐点,进入排队区这就是容量值,记录并检查哪项资源先到 80%
TPS 下降,p95 陡增,错误率上升饱和点,系统开始拒绝或崩溃停止加压,此处及以上不放进任何容量结论
TPS 抖动但 p95 稳定通常是数据或网络抖动复跑一轮,两轮一致才认

找到拐点之后,按 RBI 的路子分四层定位:网络层看带宽、丢包、连接数是否触顶;数据库层看慢查询、锁等待、连接池排队;应用服务器层看线程池、GC 停顿、队列积压;代码层看同步块、重复查询、序列化开销。四层从上往下排查,是因为越靠下的改动成本越高,先排除便宜的可能性。

判读表之外,还有一条我后来强制执行的习惯:调优一次只改一个变量,改完用同一张场景卡复跑,环境、数据量、持续时间全部不变。曾经有一轮我在同一晚改了 JVM 参数和数据库索引,结果 TPS 涨了 30%,团队很高兴,两周后才发现是那晚恰好把缓存预热时间拉长了,两个改动互相抵消了一半效果,等于白高兴。从那以后我每次做配置测试,都在场景卡里加一行“本轮唯一变量”,跑完先对照这一行再看数据,对不上就不出结论。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表