
性能测试、负载测试、压力测试的全面解析做开发、做测试、做运维的朋友应该都有过这种经历领导或者客户问“系统上线前做过压力测试吗负载能扛多少并发”结果查报告的时候发现大家嘴里说的“压测”其实五花八门有的只是拿接口工具单线程刷了几遍有的用脚本模拟了200个用户跑了一晚上还有的干脆拿FurMark把笔记本显卡烤了十来分钟就汇报“稳定性达标”。这里有个很现实的问题性能测试、负载测试、压力测试这三个词在很多人眼里几乎是同一个东西但在实际工程里它们的目标、方法和结论完全不是一回事。如果连测什么都说不清楚后面的测试数据、调优方向、上线决策就全站不住脚。这篇文章我结合自己这些年做压测、扛线上事故、帮人“擦屁股”的经验把这三种测试完整拆一遍再把JMeter、LoadRunner、FurMark这些工具怎么用、线程组怎么选、指标怎么判、上线前到底该测哪些东西一次性讲明白。适合谁来读呢刚接触性能测试的测试工程师、准备把自己的接口或小程序搞上线但又没正经做压测的开发者以及每次开会都被问“性能怎么样”但答不上来的运维同学。读完之后你至少能分清楚自己到底该做哪一类测试以及怎么把这套事从头到尾落地。1. 先搞清楚性能测试、负载测试、压力测试到底是什么很多人会把这三个测试当成同一个东西是因为它们都涉及“给系统加压、看表现”这个动作。但真正做的时候它们的测试目标、场景设计、结果评价都是不一样的。我平时给别人讲这三个概念喜欢用电梯来打比方。1.1 三个概念的正确定义性能测试Performance Testing关注的是“系统在某个既定负载下的表现是否符合预期”。还是用电梯说事一栋写字楼规定高峰期电梯往返一趟不能超过2分钟那我就在早高峰时段测一测20个人乘坐的情况下电梯实际花了多久、停了多少层、开关门是否正常。这里的核心是“验证性能需求是否被满足”负载是给定的、明确的。负载测试Load Testing关注的是“系统在预期负载范围内的表现如何变化”。比如这栋电梯设计标准是载1000公斤我依次测试10人、20人、30人、40人的情况看响应时间、故障率怎么变化找出它在接近额定负载时的表现。负载测试的核心是模拟真实工作负载验证系统在正常或稍高负载下的行为包括并发上升过程中的资源消耗趋势。压力测试Stress Testing关注的是“系统超出额定负载后会怎样极限点在哪里”。还是那个电梯我往里塞60人、80人、100人超载报警什么时候响、钢丝绳会不会崩、停止后重新启动还能不能恢复正常。压力测试的核心是找到系统的崩溃边界验证它在极端情况下的抗压能力和恢复能力。1.2 三个概念的关系与区别从目标上看三者其实是递进的性能测试回答“够不够快”基准校验负载测试回答“人多的时候还正不正常”容量验证压力测试回答“到底能承受多少人超了会不会崩”边界探索我用一个实际接口测试的例子来解释。假设一个登录接口要求是500并发下平均响应时间低于200ms错误率低于0.1%。性能测试的场景是直接打500并发跑10分钟看平均响应时间、P95、错误率是否达标。这里关注的是“是否符合指标”。负载测试的场景是从100并发开始每5分钟增加100一直加到800观察响应时间曲线在哪里开始拐弯、吞吐量在哪里停止增长。这里关注的是“容量还能不能增长”。压力测试的场景是直接上1000、1500、2000并发直到接口超时率飙升、服务重启或连接池打满再观察停止施压后服务是否自动恢复、需不需要人工介入。这里关注的是“崩溃边界在哪、恢复能力如何”。1.3 为什么这三者经常被混为一谈混为一谈的主要原因有三个。第一个原因是工具层面高度重叠。JMeter的线程组既能做性能测试、负载测试也能做压力测试差别只在于配置的参数不同导致不少人以为“用JMeter跑了就是压测了”。第二个原因是行业术语的不严谨。面试时写“精通性能测试”实际上简历上列的都是压力测试的经验领导说“做个体检”指的是性能测试但执行的人理解成了压测系统直到崩溃。这种信息损耗在工作中非常常见。第三个原因是结果呈现被简化。很多公司最终只关心“能扛多少并发”这一个数字导致负载测试和压力测试的区分在结果汇报时被彻底抹平。这带来的后果是该做性能测试验证指标时直接用压力测试把系统搞崩了最后得出的结论只有“系统太脆弱”没有具体的性能基线数据反过来该做压力测试探边界时只做了低负载的性能测试上线后流量一冲直接雪崩没人知道系统真实的极限在哪里。所以我一直建议一个完整的压测体系里性能测试、负载测试、压力测试都要做它们互相补充缺一个都不完整。性能测试负责证明系统达标负载测试负责摸清容量发展规律压力测试负责给我们兜底和预警。2. 核心性能指标解析看懂这些才能正确下结论不管用哪种工具最后落地的都是数据。但很多同学测完只会看一个“平均响应时间”这其实远远不够。我把主流的性能测试指标按类别拆开讲讲清楚每个指标的意义、坑点和判断逻辑。2.1 响应时间与百分位平均值的骗局响应时间Response Time是最直观的指标。但平均响应时间是个很容易骗人的数字因为少量极慢的请求会把平均值拉高或者大量快速请求把少数慢请求掩盖掉。我举个真实例子。某个接口测了1000次其中900次耗时80ms100次耗时800ms平均值算一下是152ms表面看挺好。但实际体验是10%的用户等了近1秒这批用户早就流失了。所以只看平均值完全不够必须看百分位。百分位响应时间的含义是假设P95 300ms意思是95%的请求响应时间小于等于300ms剩余的5%是慢请求。一般建议关注P90、P95、P99三个档位。P99能暴露那些在峰值时被挤爆的请求尤其在银行支付、电商下单这类场景P99就是真实用户体验的下限。我自己的习惯是P50中位数看整体水平P90看一般卡顿情况P95看体感变差的临界P99看最差那批请求是否严重超时如果P50很低但P99很高说明系统在某些情况下出现了明显抖动可能是GC停顿、线程池排队、数据库慢查询命中也可能是限流器触发后人为等待。这时候就要配合后端日志和服务链路追踪去定位。2.2 吞吐量TPS/QPS与并发用户数的关系吞吐量在互联网场景下最常用的是TPS每秒事务数和QPS每秒查询数。两者细微区别在于QPS偏查询接口TPS偏包含多步操作的业务事务。JMeter中有一个聚合报告里的“Throughput”字段负载测试中最核心的判断依据就是它。这里要提一个重要关系吞吐量和并发用户数不是线性增长的。随着并发上升吞吐量通常会经历三个阶段线性增长期、增长放缓期、瓶颈期甚至下降期。线性增长期系统资源充足业务处理路径顺畅并发每涨一倍吞吐量基本也翻倍。增长放缓期某个资源开始接近饱和比如数据库连接池到了上限或某个后端接口达到了自身瓶颈此时并发增加吞吐量增速下降响应时间开始拉长。瓶颈期吞吐量基本不再增长甚至略有下降响应时间剧烈恶化错误率开始抬头。这个拐点位置的价值极高。找到它你也就找到了系统的容量上限。这也是负载测试的意义所在。并发用户数这个指标也要单独提醒。很多测试人员把JMeter线程数直接当成“在线用户数”这是不对的。JMeter线程数是虚拟并发数代表同一时刻发出的活跃请求数而在线用户数是登录系统但可能大部分时间在浏览、思考的用户实际同时发请求的并发数可能只有在线人数的5%到20%。设计场景时不能把在线人数直接塞进线程组要根据业务行为的活跃比例来折算。2.3 错误率与资源利用率错误率是硬性指标通常要求低于0.1%。如果压力测试过程中错误率从0突然飙升往往意味着系统已经进入过载状态或某类资源耗尽。JMeter聚合报告中的Error %是一个重要的截停信号我压测时遇到错误率上升会先关注响应时间是否同步恶化如果两者都恶化基本判定系统到达瓶颈。但要注意错误率和响应时间不一定同步变化。有的是响应时间先拉长错误率后续才上升有的是连接池被快速打满错误立刻爆发。所以执行压测时应该同时监控错误率的变化趋势不要等到压完了才看。资源利用率包括CPU、内存、磁盘I/O、网络带宽压测过程中需要分层监控。CPU看的是内核态和用户态的占比如果用户态很高说明业务计算密集如果内核态很高可能是上下文切换频繁如果还有大量软中断则要考虑网卡多队列、中断绑核的问题。内存观察的是不光是空闲内存还要看cache/buffer、swap的使用情况。磁盘和网络也需要关注大量的慢SQL会在数据库服务器上体现为磁盘I/O等待升高带宽打满则会导致响应时间普遍增加。2.4 不同业务场景的指标关注重点没有一套指标能通吃所有业务。我根据实际业务场景大概分了以下四类第一类是面向C端用户的接口比如小程序登录、首页信息加载。这类场景最看重响应时间的中位数和P95因为直接决定用户体验。吞吐量反而不是首要关注点因为C端并发高峰通常有限更怕的是单个请求太慢导致用户流失。第二类是面向B端系统的批量接口比如对账、批量消息推送。这类场景吞吐量是第一优先级响应时间可以放宽到秒级甚至几十秒只要不超时失败即可。第三类是后台任务系统比如定时任务、定时报表生成。这类系统往往在固定时间点集中跑批压力测试重点要验证的是在极限并发执行时是否会互相争抢资源是否导致数据不一致。第四类是视频、文件类业务比如直播转推流、文件上传下载。这类场景带宽和I/O才是核心约束CPU和内存反而次要压测的重点要放在网络吞吐和磁盘顺序写入能力上。你上手一个系统时第一件事不是调工具而是先确认业务目标把指标权重定好否则测出来的数据没有参考意义。3. 工具选型JMeter、LoadRunner以及CPU和显卡压测的专用工具性能测试工具非常多每家的侧重点不一样。我按使用场景和热度把目前最常用的几类工具拆开聊聊方便你按需选择。3.1 JMeter开源界的扛把子JMeter应该是目前使用率最高的开源压测工具了纯Java开发基于线程模型模拟并发。它最大的优势是开源免费、插件生态丰富、协议支持广泛。做HTTP接口压测是它的看家本领同时它还支持JDBC、JMS、FTP、TCP、WebService等多种协议。我自己用JMeter的体会是它做接口级性能测试、负载测试、压力测试完全够用而且配合插件后在场景控制上非常顺手。但它的缺点也很明显默认线程组在长稳测试和复杂阶梯加压场景下不够灵活需要装第三方插件脚本录制功能相对简陋复杂业务流程可能需要纯手写逻辑GUI模式压测本身会有性能损耗一定要用命令行模式执行。JMeter性能测试步骤我后面单独用一个章节详细写这里先提一下基本流程创建测试计划、配置线程组、添加取样器如HTTP Request、加监听器、设置CSV参数化、命令行执行、解析报告。这套流程是一个合格测试工程师必须烂熟于心的。3.2 LoadRunner企业级重型武器LoadRunner也叫LR是Micro Focus以前是HP家的商业性能测试平台典型的重型武器。它由三大部件组成VuGen录制编写脚本、Controller设计运行场景、Analysis分析结果。LoadRunner性能测试步骤一般是这样在VuGen中录制脚本并定义事务、Run-Time Settings中设置思考时间与迭代策略、Controller中设置虚拟用户数和加压方式、执行测试同时开启系统监控最后用Analysis生成报告。LoadRunner的优势在于支持的协议非常多尤其是基于Windows的企业应用比如SAP、Citrix、Oracle Forms和传统CS架构系统JMeter很难替代。它的分析报告也很专业能自动定位瓶颈、生成图表。但缺点同样明显License费用极高动辄几十万非大厂很难承受安装部署比较重尤其是新版对操作系统和中间件有严格限制学习和维护成本高。我建议如果你的团队是中大型企业、系统结构复杂、要求全链路专业监控可以选LoadRunner如果团队预算有限、系统以Web和API为主JMeter完全够用。很多公司实际上也是JMeter为主、LoadRunner少数场景配合使用。3.3 CPU压力测试工具CPU压力测试和软件性能测试是两种思路。软件测试关注业务接口的并发能力CPU压力测试则关注硬件在极限计算负载下的稳定性和散热能力。自己组装工作站或者给服务器做硬件验证时这类工具比较常用。Linux环境下最经典的是stress和stress-ng。简单命令示例# 启动4个stress进程跑满4个CPU核心持续60秒 stress --cpu 4 --timeout 60s # stress-ng指定具体压测算法 stress-ng --cpu 4 --cpu-method matrixprod --timeout 60s我自己的经验是stress-ng比stress功能丰富很多它不只可以压CPU还能压内存、磁盘、网络、进程数适合做全面硬件稳定性测试。运行stress-ng的时候建议配合顶层监控工具比如top、htop、mpstat观察每个核心的使用率和温度。另外压力测试过程中还要重点观察CPU的频率和温度。正常跑压力状态时CPU频率应该保持在高位温度根据散热系统不同会稳定在某个区间。如果温度撞墙到一百度上下频率大概率会降下来就说明散热有问题了这时候压测结果的实际意义也就不大了。Windows平台下常用工具是IntelBurnTest、Prime95、AIDA64系统稳定性测试。这些工具基本都会把CPU指令集跑到极限让处理器短时间内全负荷运转是判断CPU是否稳定、散热是否达标的实用手段。3.4 显卡压力测试工具FurMark显卡压力测试和CPU类似核心也是验证硬件在高负载下的稳定性和散热。这里最出名的工具就是FurMark它的界面里那只毛茸茸的甜甜圈几乎成了硬件圈“烤机”的代名词。FurMark的工作原理是调用GPU渲染复杂的毛发特效把显卡的着色器、显存、供电全部推到高负载状态。常见的帧数监测工具包括MSI Afterburner、GPU-Z可以同时监控GPU温度、显存温度、核心频率、显存频率、风扇转速、功耗等数据。我来说一下实操细节跑FurMark之前先看显卡默认温度和风扇曲线然后选择预设分辨率1080P或者2K都行建议开8倍抗锯齿或者不开看你要验证什么负载。分辨率越高、抗锯齿越高GPU负载越重。一般烤机20到30分钟温度曲线平稳不持续上升、画面不花屏不闪退、风扇转速正常就算是通过。烤机时间太短没有意义因为温度传导到散热器和机箱内部需要时间前几分钟并不能代表稳态温度。FurMark跑的时候你会看到GPU功耗直接拉满如果电源功率不足或供电设计有问题会直接黑屏重启这也是一种验证方式。但我要提醒一点新显卡跑FurMark时如果不想损坏硬件就提前关注温度曲线一旦发现温度异常升高或频率骤降说明散热压不住建议立刻停止烤机并检查机箱风道。4. 完整的压力测试实操流程以JMeter为例做压力测试前很多人一上来就打开JMeter、添加线程组、填个1000并发然后跑发现系统崩了却说不清是哪个环节崩的。这其实是不科学的方法。我现在把一套完整可复用的流程拆出来搭配热词“jmeter性能测试步骤”和“压力测试选择什么线程组”一起讲。4.1 压测前的准备压测开始前有四件事必须确认清楚。第一明确压测目标。这次是测单个接口的极限并发还是测某个核心链路的容量还是验证系统的恢复能力目标决定了线程组、持续时间和结果分析方式。第二准备独立的压测环境。最理想的是独立测试环境配置尽量与生产一致。如果只能在生产环境压测就必须在低峰期进行并且要设置熔断和降级预案。如果压根没有独立环境那至少保证压测数据写入的库和缓存与线上隔离避免脏数据污染正式数据。第三铺底数据。数据库要准备足够的数据量比如一个列表接口如果表里只有几百条数据压出来的接口性能毫无参考价值。生产环境可能有几百万条而测试环境的库只有几千条结果差异巨大。第四监控工具先行。至少要有基础监控服务器CPU、内存、磁盘、网络数据库连接数、慢查询数以及应用本身的JVM内存、GC日志。没有监控的压测等于闭着眼睛开车出了问题只能猜。4.2 线程组怎么选JMeter里线程组的选择直接决定了压力模型这是新手比较容易困惑的地方。默认的Thread Group很“直白”可以设置线程数、Ramp-up时间、循环次数适合简单的性能测试和固定负载的压测但它的加压方式比较粗比如设置“线程数1000Ramp-up60秒”大致是每秒增加16到17个线程但是具体的增量曲线不够平滑也不方便做阶梯式加压、阶段维持。如果你做的是压力测试我更推荐使用Ultimate Thread Group或Concurrency Thread Group。这两个需要通过JMeter插件管理器安装“Custom Thread Groups”插件。Ultimate Thread Group可以配置多个阶梯每一行代表一个阶段。比如第一行“100线程启动时间60秒持续300秒”第二行“200线程启动时间60秒持续300秒”这样就能模拟系统逐步加压的过程每个台阶持续一段时间直到系统出现拐点或崩溃。这个方式我非常推荐因为它能清晰看到系统在哪个并发区间开始劣化。Concurrency Thread Group则更适合做固定并发的持续压力它的核心参数是Target Concurrency可以直接从当前并发数开始保持稳定运行。它的调试更平滑适合长稳测试和压力恢复测试。4.3 脚本编写与参数化写JMeter压测脚本的核心是尽可能模拟真实用户手段就是参数化和关联。参数化是防止所有线程都用同一份数据。举个例子压测一个查询订单接口如果所有虚拟用户都查同一个订单号那么数据库大概率会把这个订单号对应的数据页都缓存到内存里后续所有请求都命中了缓存测出来的结果会异常好看但与真实场景完全不符。实际操作中我一般用CSV Data Set Config配合外部的用户数据文件。文件里放一批用户ID、商品ID、优惠券ID线程通过变量引用按顺序或随机取用。这样每个线程拿到的参数不同命中不同数据分区更接近真实情况。关联则是处理动态参数。比如压测一个需要登录态的业务登录接口会返回token后续接口都需要带上这个token。这时需要用JSON提取器或正则表达式提取器从登录响应中提取token存到JMeter变量中然后在后续请求中使用。如果压测的是登录接口本身那么就不能用固定账号否则验证码、单点登录锁定、单用户被多端踢下线等问题都会出现导致压测数据失真。建议准备一批测试账号开启账号解锁和验证码旁路开关。4.4 场景执行与监控JMeter脚本建议在命令行模式运行而不是GUI模式。jmeter -n -t signin.jmx -l result.jtl -e -o report参数解释一下-n是命令行模式-t指定测试计划文件-l输出原始结果文件JTL格式-e生成HTML报告-o指定报告输出目录。这个命令会生成一个非常直观的HTML报告包含TPS、响应时间分布、错误率等多种图表。压测执行过程中监控是多维度的。我习惯开三个窗口同时看一个窗口跑JMeter命令看终端输出误差一个窗口看应用服务器的资源状态top、free、iostat、vmstat还有一个窗口看中间件和数据库的状态。后端常见的报警指标是连接池活跃数、线程池排队数、GC频率和耗时一旦这些异常就要立刻回去查代码或配置。压测时间也要控制。简单的接口性能测试跑10到15分钟足够负载测试建议每级负载稳定5到10分钟压力测试的极限段如果系统已经开始报错再持续压10分钟左右只是为了观察是否雪崩或是否会自动恢复不建议长时间硬扛。4.5 结果分析与调优压测结束之后最重要的环节是结果分析。先看聚合报告再结合后端监控数据归因。这里有个常见的误区很多人一看到响应时间长了就急着调代码或加缓存。但压测报告中响应时间变长的原因可能是多方面的所以一定要层层下钻。从网络层看是否客户端JMeter本机带宽打满连接复用是否正常从应用层看线程池是否排队GC是否频繁从数据库层看连接池是否打满慢SQL是否增多。定位到具体瓶颈后再做针对性优化否则容易白费力气。针对常见瓶颈有一些通用优化手段我简单列一下方便参考如果CPU使用率接近100%查是否有耗CPU的业务逻辑比如正则解析、加密算法、大量日志输出优先优化逻辑和降低重复计算如果内存持续增长一个可能是JVM堆内存GC不回收试增加堆内存并优化GC参数但如果是内存泄漏那就需要借助堆转储分析工具定位如果线程池排队严重调大线程池上限但同时要注意线程切换开销和数据库连接池的承受能力如果数据库慢查询高开始检查SQL索引、避免全表扫描、考虑加缓存、分库分表等方案如果网络带宽打满那就压缩接口响应体、升级带宽或调整传输协议调优后要重新压测验证是否改善。性能调优往往是个循环至少要压三轮初始基准、调优后复测、最终确认。5. 小程序上线前要做压力测试吗还要做什么类似测试这是一个热度很高的问题尤其现在很多团队做小程序、H5应用上线前只知道要做功能测试却忽略了后续的分类质量验证。我的态度很明确小程序上线前一定要做压力测试但这只是其中一环还要配合其他类型的测试才能最大程度避免上线事故。5.1 必须做的测试类型小程序的测试体系我一般拆成三个层面前端客户端测试、服务端接口测试、整体链路测试。前端客户端测试重点是小程序本身的功能正确性、启动性能、页面渲染性能、兼容性。小程序不像原生的App那样可以做流畅的启动耗时、内存占用的弱测试但启动时间、分包大小、首屏渲染时间这些指标是可以在开发者工具里看的。微信开发者工具中有一个“体验评分”可以检查加载性能、运行性能等建议发版前跑一遍踩坑。不同机型和微信版本、不同操作系统都需要在核心机型上过一遍特别是低端安卓机前端性能问题往往在那里暴露。服务端接口测试这是压力测试的重点。小程序上线前要针对核心链路做接口级的性能测试。对于小程序来说登录态校验接口、首页信息接口、列表查询接口、交易下单接口这四类通常要重点压。因为这些接口承载了绝大多数用户流量一旦瓶颈挂掉整个小程序都会出现白屏或操作停滞。服务端接口的响应时间指标建议P95控制在300ms以内失败率低于0.1%。整体链路测试则是对“小程序 - 网关 - 业务服务 - 数据库/缓存”的完整链路进行压测验证全链路中间件和基础依赖的容量。很多团队只测了业务服务本身忽略了网关、Redis、数据库各自独立部署的连接数和超时配置链路一长问题就多。整体链路压测能真正暴露跨服务调用时的超时和熔断问题。5.2 小程序压测的注意点小程序压测和普通Web压测有三个明显的区别。第一接口特点不同。小程序接口走HTTPS还需要带登录态压测时要先解决token获取和session保持的问题。另外不少小程序接口使用POST JSON格式JMeter里需要添加HTTP头管理器设置Content-Type为application/json。第二网络环境的影响更大。用户经常在弱网环境下使用小程序所以除了常规压力测试还建议做弱网测试。这可以通过JMeter的模拟网络带宽延迟插件或者Charles、Fiddler等的弱网设置来做模拟“3G网络”、“高延迟”、“丢包”的场景观察接口超时和体验降级是否可接受。第三联动业务系统要考虑幂等和防重复。压测下单、支付这类写操作接口时很可能产生大量真实订单数据或重复请求。建议压测环境单独部署一套测试库或者在上游接口做好幂等处理。我的经验是支付相关接口尽量通过沙箱环境来压避免产生真实资金流水和相关限制。5.3 上线前的验收清单我通常给团队一个很朴素但也实用的checklist上线前照着走一遍[ ] 功能测试已完成核心流程用例全通过[ ] 性能测试覆盖核心接口P95响应时间在公司约定阈值内[ ] 负载测试完成明确系统容量上限并确认距离线上预估峰值有至少30%缓冲[ ] 压力测试完成系统在极限并发下不会出现雪崩能通过限流或熔断自我保护[ ] 弱网测试完成在弱网环境下接口主要错误被捕获、页面有合理提示[ ] 兼容性测试完成核心机型、核心微信版本跑通[ ] 安全测试完成接口无越权、SQL注入等基础问题[ ] 监控报警已配置线上关键指标可观测这个清单里的每一项具体情况可以根据团队规模调整但至少要保证“性能测试 负载测试 压力测试 弱网测试 兼容性测试 安全测试”这个组合不缺席缺一项上线后出问题的概率就大一分。6. 常见问题与排查技巧实录压测过程中的坑我踩了太多次了。这里挑一些高频问题按问题的现象、原因、排查思路整理出来算是给自己的经验存档也希望能帮你少走点弯路。6.1 压测结果不稳定的原因最典型的现象是同样的脚本、同样的线程数今天跑数据很好明天跑数据明显变差或者连续跑两次结果差异很大。如果没有代码变更大概率是压测环境存在干扰因素。排查思路如下先看压测机本身也就是JMeter所在机器的CPU、内存、网络是否被其他任务占用。JMeter在压测高并发场景下本身也是消耗资源的如果一台机器只有2核4G就去跑5000并发JMeter自己的线程调度就会导致大量延迟压测结果完全失真。参考经验是压测机至少4核8G跑高并发时建议分布式压测至少准备2到3台施压机避免客户端成为瓶颈。再看被测环境是否有定时任务、夜班批量任务在跑。我曾经遇到一个项目每天晚上10点数据库会自动跑统计任务于是我晚上10点的压测数据异常恶化。后来把压测时间避开批量任务周期数据就正常了。最后检查网络链路。虽然一般都在内网压测但网络交换机拥塞、防火墙策略调整都可能引入额外的延迟。一般先ping一下目标服务器确认为分布时延稳定再进行压测才有可比性。6.2 服务器CPU飙升到100%怎么办压测过程中CPU直接打满是很常见的情况但CPU打满不一定等于系统问题关键看是哪个进程或哪个线程在消耗CPU。先用top命令看整体负载再用top -Hp 进程ID查看具体线程的CPU使用情况然后通过线程ID去查对应业务日志。如果是Java应用可以用jstack把线程堆栈导出来定位是GC线程频繁、业务线程死循环还是等待锁。从我的经验看Java服务CPU飙高最常见的原因依次是复杂业务逻辑或正则计算、频繁的序列化和反序列化、JVM频繁Full GC、死循环或空转代码。搞清楚原因后对应的解法也不同。有的是优化代码比如用更轻量的序列化方案或缓存正则表达式有的是调整JVM参数比如让堆内存更大、选择合适的GC器有的是排查代码逻辑问题。这里强调一点压测时CPU打满不一定说明程序代码有Bug也可能是系统本来就该在极限负载下把CPU用满硬件成本就是为了支撑这种负载的。判断标准还是看业务指标是否达标响应时间是否还能接受。6.3 响应时间从哪一级开始分析响应时间变长很多人都慌了有些人直接去看数据库慢日志有些人去查网关配置。但我的习惯是层析定位从客户端视角一层层往下追。使用JMeter压测时默认的响应时间包括了从发起请求到接收完整响应的时间这个时间在网络层面包含了连接建立时间、处理时间、响应传输时间。如果响应时间长了第一件事是看是不是程序连接服务器这一步变慢。如果Connect Time这个值明显偏高说明网络或服务器连接队列出现了拥塞可能是TCP全连接队列满了也可能是后端应用线程池连接不上。如果Connect Time正常但请求处理时间很长重点排查应用服务器的线程池和GC。如果应用服务器各项指标正常再看依赖的数据库和缓存。数据库这边重点看连接池是否耗尽、慢SQL数量是否增加、锁等待是否严重。缓存是重点关注是否存在热点键和缓存穿透大量请求打到数据库。沿着这条链路逐层拆解大部分性能瓶颈都能被快速定位。6.4 压测时容易踩的坑这里把我踩过的一些高频坑罗列一下算是提醒。第一压测集合时频繁新建TCP连接把性能问题测成了连接问题。性能测试过程中应该开启连接复用让请求复用同一个连接通道而不是每次建立新的连接否则测出来的瓶颈可能是连接的开销而不是业务本身。压测前要看JMeter脚本里的HTTP请求设置确认连接是否保持复用。第二不设思考时间把测试做成极限压力实际用户操作之间是有间隔的用户不可能毫秒不停地在界面上点。性能测试阶段要设置合理的思考时间模拟真实行为压力测试阶段则不应该考虑思考时间目的就是尽量压满。第三忽略JVM参数对测试结果的影响。同一套代码JVM堆大小不同、GC算法不同压测结果可能相差好几倍。所有对比压测必须在一致的JVM参数下进行。第四只看平均不看重负载拐点。压测报告不要只写“平均响应时间200ms”要画出不同并发下的Tps和响应时间趋势图标出拐点和崩溃点。这样上线前的容量评估才有意义。第五数据没有清理越压越慢。如果压测过程中产生了大量脏数据并且没有清理就进行下一轮压测数据库表膨胀、索引维护、缓存失效都会让后面几轮的结果异常。每一轮压测结束尽量重置数据库到初始状态或者至少清理本轮的坏数据。7. 最后分享一点个人经验说了这么多工具、指标、步骤每次给团队做压测培训和方案评审的时候我最后都会放一句总结性的话性能测试、负载测试、压力测试不是一次性的“过场”而是一个持续循环的过程。项目上线前做一轮完整的体检部署变更后做一轮回归验证线上指标异常时再做一轮定向排查这样才能让系统始终处于可控状态。我个人在实际操作中的体会是压力测试是最容易发现团队协作堵点的环节。它逼你梳理清楚每个接口的依赖关系、每个组件的配置细节、监控是否完善、响应预案是否落地。很多时候压测结论早就不是技术问题而是流程问题和管理问题。最后再分享一个小技巧压测报告的模板最好在项目早期就确定下来统一格式。无论是性能测试还是压力测试都写明测试环境、压测工具参数、监控数据、结论和调优建议这五块内容。这样后续做横向对比时就不会因为每份报告格式不同而花费大量时间去对齐归档和追溯都会方便很多。如果你正打算开始给你手上的系统做第一次压测那就从搭建一套JMeter脚本、设置好监控、先跑一个性能测试开始吧。等这轮流程走通了再慢慢扩展做负载测试和压力测试整套体系自然就建立起来了。