去年有个朋友接手了一个即将上线的电商项目内部测试一切正常结果上线当天用户一多登录接口直接超时订单居然下不进去。会议室里一片沉默所有人盯着监控大屏半天没人说话。后来排查发现数据库连接池配置得太小高峰期几百个并发请求一拥而入连接直接被打满。我这个朋友后来跟我说了一句让我印象很深的话功能测试证明系统能跑性能测试才证明系统扛得住。这句话基本可以概括JMeter对于新手的第一层价值。JMeter是一款开源、纯Java实现的性能测试工具它可以模拟大量用户同时访问你的系统帮你提前发现系统在哪里会撑不住、什么时候开始变慢、错误率从哪个点开始飙升。这篇文章就是写给完全没接触过性能测试的小白的我会从最基础的概念讲起带着你装好工具、写出第一个测试脚本、跑通一次压测、再告诉你结果该怎么看、踩过的坑有哪些。内容尽量接地气不堆术语但该讲清楚的地方一个都不省。1. 性能测试到底测的是什么1.1 为什么要做性能测试功能测试关注的是“对不对”输入一个值输出是否符合预期。性能测试关注的是“快不快、稳不稳、能扛多少”。同一个接口单个人访问可能只要50毫秒但1000个人同时访问可能需要5秒甚至直接报错。这个“人多就卡、人更多就崩”的问题就是性能测试要解决的问题。放在日常场景里性能差的体验是每个人都能感受到的电商大促页面转圈、抢票系统卡死、购物车结算反复失败、直播弹幕延迟越来越严重。这些问题如果在上线前没发现就是事故如果上线前用JMeter测出来了就只是一个可以被修复的Bug。很多团队把性能测试当作上线前的“加分项”其实它是“保命项”。有的人可能觉得我们系统用户量不大根本没到要谈性能的阶段。但性能问题不只会出现在大规模并发场景。一个后台报表功能数据量从10万涨到1000万即使只有一个用户在用响应时间也可能从1秒变成30秒。这类问题靠功能测试永远测不出来必须通过模拟特定负载和长期运行来暴露。所以性能测试不只是给大厂准备的只要你的系统会随着数据增长、用户增长产生变化你就需要它。1.2 性能测试的典型类型和核心指标性能测试不是一个动作而是一类动作的总称。不同类型的测试关注的问题不一样负载测试核心目标是验证系统在预期负载下表现是否符合要求比如“500人同时在线时响应时间不超过3秒”。压力测试持续加大负载直到系统崩溃找到系统的上限和崩溃方式比如“多少人同时访问时系统开始报错”。容量测试关注系统能承载的最大用户量或数据量往往用于容量规划。稳定性测试让系统在正常负载下跑几个小时甚至几天观察内存是否泄漏、响应时间是否逐渐变慢。新手最容易混淆的是负载测试和压力测试。打个比方负载测试是问“路况好的时候这条路能跑多快的车”压力测试是问“一辆车都堵死的时候这条路是怎么瘫痪的”。两者的目的不同脚本设计思路也不同。无论哪种类型大家最终都要盯住几个核心指标。新手不需要记住几十个指标先把这四个看懂大部分场景已经够用了响应时间从发起请求到收到完整响应所花费的时间。通常看平均值意义有限因为少数慢请求会拉高均值更建议关注90% Line90%的请求都在这个时间内完成。吞吐量TPS每秒系统处理的请求数或者事务数。注意区分“系统能处理多少”和“你压进去多少”比如你每秒发出1000个请求但系统每秒只处理500个这时系统已经超负荷了。错误率失败请求的占比。正常情况错误率应该是0压测时如果出现高于0的错误率哪怕只有0.1%也要查明原因。并发用户数同一时间正在和系统交互的用户数。注意“并发用户数”不等于“每秒请求数”一个用户在一段时间内可能连续发出好几个请求。这四个指标不是孤立看的。比如并发用户数从100涨到200时响应时间可能从500毫秒涨到800毫秒这还算线性增长如果涨到210时响应时间直接跳到3秒错误率开始冒头说明系统已经被推到临界点了。临界点就是性能测试最想找到的东西。2. 为什么选JMeter以及环境准备2.1 工具选择JMeter为何适合新手市面上能做性能测试的工具不少商业的有LoadRunner开源的有JMeter、Tsung、Gatling、k6等。为什么我建议新手从JMeter入手最重要的原因是它是全平台图形化工具不需要像Gatling那样写代码也不需要像LoadRunner那样搭一套复杂环境。装好之后左键拖拽组件就能搭出一个测试计划对完全没接触过脚本的用户非常友好。JMeter本身是纯Java写的所以跨平台能力很强Windows、Linux、macOS都能跑。同时它支持HTTP、HTTPS、WebSocket、数据库、FTP、JMS等协议虽然新手接触最多的是HTTP接口但后面你如果要做数据库压测或者消息队列压测它也能覆盖。插件生态也很丰富常用的插件有JMeter Plugins Manager可以用来扩展更丰富的监控指标和图表。还有一个很现实的因素免费。性能测试通常需要多轮反复执行商业工具按年收费价格不低而JMeter是开源免费的许可成本为零。对于个人学习或者企业内部使用来说这几乎是决定性优势。和k6、Locust这类工具相比JMeter的劣势是脚本比较笨重、资源占用稍高、原生图表不美观。但这些问题对一个新手来说远没有“门槛低、资料多、上手快”来得重要。先用JMeter把性能测试的思路跑通之后如果需要更高性能的压测方案再考虑迁移到其他工具也不迟。2.2 安装与环境变量配置JMeter运行依赖Java环境所以第一步是装JDK。版本选择建议如下JMeter 5.4以上版本建议搭配Java 8/Java 11/Java 17具体看你的JMeter版本说明。装完之后在命令行输入java -version确认能正常输出版本号。下载JMeter时建议从官方网站获取最新稳定版下载下来的压缩包解压到本地目录目录路径尽量不要有中文和空格否则后面某些场景下会出奇怪的问题。解压后的目录结构里bin目录存放启动脚本lib目录存放依赖JAR包docs目录是官方文档。启动有两个方式Windows下双击bin/jmeter.bat启动图形界面macOS/Linux下执行bin/jmeter.sh。启动后你会看到一个菜单栏加一棵树状结构的界面和你想的不太一样不用担心这个界面就是JMeter的主界面所有的测试组件都挂在中间的测试计划节点下。注意JMeter的默认JVM内存配置比较保守实际压测时如果并发数稍微大一点很容易出现内存溢出。建议在bin/jmeter.bat或bin/jmeter.sh中找到堆内存配置项把初始堆和最大堆调大比如设置为HEAP-Xms2g -Xmx4g。这个我后面在常见问题部分还会详细说。装好之后建议先做一个最简单的冒烟验证打开JMeter右键测试计划添加一个线程组在“查看结果树”里能看到请求结果就说明环境是通的。第一次跑通比一次学好多功能重要得多工具环境没问题后面所有内容才有落点。3. 第一个测试计划从零跑通一次压测3.1 创建线程组并发用户怎么理解打开JMeter后你会看到左侧树形结构里有一个默认的“测试计划”。右键测试计划选择“添加” - “线程用户” - “线程组”这就是你的第一个核心组件。线程组可以理解成一组虚拟用户的集合。它有三个关键配置线程数相当于虚拟用户的数量。设成50就代表模拟50个用户同时操作。Ramp-Up时间秒启动全部线程所需要的时间。设成10秒代表这50个用户会在10秒内逐步启动而不是瞬间全部涌进去。循环次数每个线程执行脚本的次数。设成1代表每个用户只跑一次勾选“永远”代表持续循环直到手动停止。新手最容易犯的错误是把Ramp-Up设置成0那样等于所有用户在同一瞬间发起请求这在实际业务中几乎不会出现。真实用户是陆陆续续进入系统的所以Ramp-Up时间应该根据场景去设计。如果你不确定可以先从“线程数100、Ramp-Up设为100秒”开始也就是平均每秒钟只启动1个用户系统压力是慢慢加起来的这个节奏相对温和也更容易观察系统指标的变化过程。为了控制测试时间建议使用调度器功能把“调度器配置”里的“持续时间秒”设为600这个测试就会在600秒后自动结束不用手动点击停止。为什么线程组的设计这么重要因为它决定了你的压测模型是否符合真实情况。一个没有Ramp-Up的压测测出来的“崩溃点”往往是人为制造出来的瞬时峰值而不是系统真实承载能力的体现。我见过不止一个项目就是因为压测时全部线程瞬间压上去把系统打到假死然后所有人误以为系统性能太差结果排查了三天才发现是压测方式的问题。所以线程组配置不是一个填数字的步骤而是测试设计的一部分背后的逻辑是想清楚你的用户是怎么进入系统的。3.2 添加HTTP请求和查看结果线程组建好之后现在要让这些虚拟用户真正去访问你的系统。右键线程组选择“添加” - “采样器” - “HTTP请求”这是整个脚本的主体。HTTP请求的几个核心配置项如下协议http或者https注意如果服务器配置了HTTPS但这里填了http请求会直接失败。服务器名称或IP填域名或IP地址例如www.example.com或者192.168.1.100。端口号默认80端口可以不填HTTPS默认443如果是其他端口比如8080必须显式填上。方法GET、POST、PUT、DELETE等根据接口实际情况选择。路径接口的URL路径例如/api/login。参数GET请求的参数可以直接添加POST请求的表单参数也可以在这里添加。如果是JSON格式的请求体需要切换到“消息体数据”页签填入JSON内容。配置完成后还需要加一个“查看结果树”监听器才能看到请求和响应内容。右键线程组选择“添加” - “监听器” - “查看结果树”。这个监听器可以展开每个请求看到请求头、请求体、响应状态码、响应内容。建议先设成1个线程、循环1次跑一次看结果树里的响应是否符合预期。这一步本质是调通脚本只有脚本通了后面的压测才有意义。很多新手一开始就设了100个线程直接跑结果脚本本身是错的弹出一堆报错自己也不知道是脚本问题还是系统问题。调试时优先看响应状态码200代表正常404是路径不对500是服务器内部错误302是重定向。如果返回的是错误信息去响应体里看具体的报错内容大部分错误在响应体里都能找到答案。学会看响应内容是排查一切压测异常的第一步。3.3 聚合报告怎么看脚本调通之后把线程数改成你想要的压测规模然后把测试跑起来。结束后右键线程组添加一个“聚合报告”监听器这是JMeter里最常用、信息量最大的一张报告表。聚合报告中有几个字段按重要程度依次说明Label采样器名称一般对应事务名或接口名。Samples完成的请求总数如果设置了100个线程循环10次这里就是1000。Average平均响应时间单位毫秒反映整体性能但容易被极端值带偏。Median中位数响应时间一半请求高于这个值一半低于这个值比平均值更能反映典型体验。90% Line90%的请求都在这个时间内完成。这个值比平均响应时间更适合作为性能达标的标准。Min / Max最短和最长的响应时间。Max值异常高时要关注是否存在偶发超时或Full GC。Error %错误率正常情况下必须是0%任何非0错误都要查清楚。Throughput每秒处理的请求数这就是前文说的TPS系统吞吐量的核心指标。看报告不能只挑一个字段说结论。比如平均响应时间只有300毫秒但90% Line是5秒说明有不少请求很慢平均值被大多数快请求拉平了这种系统性能体验其实很差。再比如TPS很高、错误率也高说明系统处于忙乱状态一部分请求被放弃这时候不能认为“处理能力很强”。对比多轮测试的报告是分析的关键步骤。第一轮50并发第二轮100并发第三轮200并发把每轮报告的90% Line和TPS记下来做成一张简单的表格。你会发现通常存在一个临界点100并发时TPS还在涨200并发时TPS反而掉了响应时间暴涨错误率上升。这个临界点就是系统性能的瓶颈所在。找到它性能测试的核心任务就完成了一大半。4. 真正可用的小白必备技巧4.1 参数化让每次请求都不一样实际业务里100个用户同时登录用户名和密码不可能都是同一个。如果所有虚拟用户都用同一组数据后端去重、缓存这些机制会把压测结果搞得很失真。参数化就是让每个虚拟用户、每次请求使用不同数据的关键手段。其中最常用的组件是CSV Data Set Config。准备一个CSV文件第一行是字段名比如username,password下面每行就是一组数据。在线程组下面添加“配置元件” - “CSV Data Set Config”配置文件名路径、变量名称与CSV第一行对应、分隔符、是否循环读取数据等。然后回到HTTP请求里把用户名一栏直接填成${username}密码填成${password}运行时JMeter就会自动从CSV文件里按行读取数据。需要注意默认情况下多个线程同时启动时每个线程拿到的数据行可能会被抢占导致同一个用户被多个线程重复使用。如果每个虚拟用户需要使用唯一、独立的账号建议勾选“共享模式”为“每个线程”并且在CSV第一列放唯一的用户名。如果接口本身允许数据重复比如只是查询商品列表那参数化不做也行。参数化真正要解决的是测试数据隔离问题。举个例子压测一个下单接口如果没有参数化所有线程都用同一批库存前几个请求就把库存锁住了后面的请求全报“库存不足”错误率瞬间飙升。不了解内情的人以为系统扛不住并发实际上只是数据被用完了。所以遇到错误率异常升高时先想想是不是数据和参数化的锅。4.2 断言让脚本自己判断对错没有断言的时候接口返回“200”就算成功但实际返回的可能是一串错误JSON比如业务报错“用户不存在”。200代表HTTP层通了不代表业务层正确。性能测试不仅测服务器压力也要验证在各种压力下业务逻辑是否依然正确。这就需要用断言来做结果校验。最常用的是“响应断言”。右键采样器添加“断言” - “响应断言”。在“要测试的响应字段”里选择“响应文本”然后在“模式匹配规则”中选择“包含”在下方文本框中填入一个你期望出现的关键词。比如登录接口正常返回时会包含“success”你就在这里填success。运行时如果响应体里没有这个关键词JMeter会把这个请求标记为失败错误率随之上升。这样做的好处是你可以从错误率指标里直接看出业务失败情况而不仅仅是网络层错误。比如压测到300并发时HTTP 200响应数量没变但成功率断言开始大面积失败说明系统返回了业务上的降级信息或异常提示这个信息量比单纯看错误代码要丰富得多。不过断言也不能滥用。每增加一个断言JMeter就要对每个请求做一次文本匹配断言太复杂会消耗JMeter自身的CPU资源间接影响压测结果的准确性。我的经验是一个接口只加一条最关键的断言验证一个必返回字段就够了不要多。4.3 关联拿到动态返回的数据压测过程中经常遇到一种情况第二个请求需要用第一个请求返回的数据。最典型的场景就是登录后拿到Token然后带着这个Token去查询用户信息。如果Token每次登录都会变你就必须在脚本里把Token提取出来并传给下一个请求这个技术叫关联。JMeter里做关联最常用的两个组件是正则表达式提取器和JSON提取器。如果返回结果是JSON格式强烈建议用JSON提取器配置比正则简单得多。以提取Token为例添加“后置处理器” - “JSON Extractor”变量名称填tokenJSON Path表达式填$.data.token匹配数字填1。运行一次之后Token就被保存到了变量token里后面其他请求的Header或者请求体里直接用${token}引用即可。正则表达式提取器更通用适合返回HTML或XML的场景。核心就是写一条正则比如token:(.?)然后通过捕获组把它提取出来。正则表达式里用()括起来的部分才是要提取的内容用.?表示非贪婪匹配避免匹配多个值。新手最容易在这个组件上卡住建议先在“查看结果树”里确认响应文本的实际格式再对应写正则。关联是很多小白觉得最难的一环但其实它解决的是一个非常实际的问题有状态的接口压测。如果不做关联第二个请求永远用旧的Token到一定并发量时段Token被服务端清除请求全部报401压测数据全废。做好关联之后每个虚拟用户都是真实的完整业务链路这样的压测才贴近线上。4.4 模拟真实用户节奏定时器一个真实的用户打开页面后不会一秒不停地点击他会浏览、思考、填表中间隔着一段延迟。压测时如果没有这个延迟所有请求以极限速度连续发出测出的是“最大吞吐能力”而不是“真实用户体验”。定时器就是给脚本注入“思考时间”的工具。最常用的是“固定定时器”和“高斯随机定时器”。固定定时器让每个请求之间固定等待N毫秒简单但过于机械高斯随机定时器在指定平均值和偏移范围内随机等待更符合真实用户的操作节奏。比如期望平均思考时间为3秒可以设置高斯随机定时器平均3000毫秒、偏移500毫秒那延迟大约在2500到3500毫秒之间浮动。需要注意的是定时器属于“逻辑控制”它影响的是整个采样器的节奏。你加了定时器之后同一个线程组里的所有HTTP请求之间都会插入延迟。如果想要控制得更精细可以把定时器只挂在某个采样器下面或者使用“吞吐量定时器”来精确控制每分钟请求数。思考时间设多长合适要看你压测的是什么场景。比如搜索接口用户一般看完结果再搜思考时间1到3秒合理登录接口用户输密码也需要几秒。更科学的做法是去找产品或者运营要真实的用户行为数据没有数据时先用2到3秒作为默认值跑一遍观察TPS是否符合预期的业务目标再调整。5. 结果分析与瓶颈定位5.1 关键指标判读错误率、TPS、响应时间一次压测跑完之后第一步不是分析而是确认这轮测试数据是否有效。什么情况下数据无效比如脚本报错率高是因为参数化数据被用尽比如压测机自身CPU打满导致结果失真再比如网络抖动产生大量超时。数据无效时后面的分析全是白费功夫所以先花五分钟检查基础环境再开始看指标。确认数据有效之后看报告的优先顺序应该是错误率 - TPS - 响应时间 - 资源使用情况。错误率是硬指标只要不是0就要追查TPS和响应时间结合着看才能判断系统是“撑不住”还是“变慢了”。这里分享一个我的个人判断法把并发数往上加观察TPS变化。如果TPS跟着并发数上升一起上升说明系统还有余力如果TPS上升变缓然后持平说明快到瓶颈了如果TPS不升反降那就说明系统已经过载这时响应时间和错误率通常会同时恶化。找到TPS由升转降的那个并发数就是系统的容量拐点。响应时间的分析方法重点是看分布而不是看平均值。建议同时也看90% Line和Max值。如果90% Line还好但Max非常高说明存在少量长尾请求可能是GC停顿或者网络波动如果90% Line和Average一起涨说明整体都在退化。通过多轮数据的纵向对比比单轮数据更能看清楚性能变化的趋势。5.2 怎么区分网络瓶颈、应用瓶颈、数据库瓶颈发现性能瓶颈之后下一个问题是瓶颈到底在哪一层这是一个综合性排查工作但新手可以先学会最简单的分层思路。第一层看网络。如果错误信息里出现Connection timed out、Connection reset先ping或telnet确认网络链路是否稳定再观察是否是压测机网络带宽打满。本地压测时网络问题往往体现在延迟高但不报错压测机和服务器在跨机房场景下更容易出现这类情况。第二层看应用服务器。在压测过程中同时盯CPU和内存CPU如果持续接近100%说明应用在做大量计算或者线程切换要先看有没有死循环、高消耗的日志输出内存持续上涨且不回落怀疑内存泄漏。推荐的工具是top、jstat、jmap这三个能解决大多数Java应用的问题。第三层看数据库。面向数据库的典型瓶颈是连接池耗尽、慢SQL、锁竞争。连接池耗尽的现象表现为应用日志里有“获取连接超时”之类的错误慢SQL可以用数据库慢查询日志定位锁竞争要看等待时间和阻塞数量。如果应用服务器CPU不高、但请求响应时间还是长大概率是数据库端卡住了。大多数性能瓶颈最终都落在数据库这一层因为数据库的并发处理能力和连接资源有限。排查时我习惯的顺序是先确认压测机和服务器本身没问题再看应用CPU内存再查数据库慢SQL和连接数。从外部往内部一层层剥比一上来就翻代码要高效得多。6. 常见问题与排查速查6.1 连接超时与连接复用新手跑JMeter时最常见的错误之一是报错信息里出现ConnectException: Connection refused或者Connection timed out。Connection refused一般连不上目标服务器先确认地址和端口对不对、服务是否启动、防火墙是否放行。Connection timed out通常是网络不通或者目标服务器负载太高大量请求处理不过来堆积在队列里新的连接只能排队直到超时。还有一种隐蔽情况是压测机本身文件句柄不够用。一个TCP连接对应一个文件句柄并发数一大超过系统默认限制就会报SocketException: Too many open files。Linux下用ulimit -n查看默认限制一般默认是1024做压测时建议把这个值调大改成10240或者更大。另外建议在HTTP请求里开启KeepAlive也就是默认自带的连接复用。HTTP采样器下方可以勾选“使用KeepAlive”这能让同一个虚拟用户的多个请求复用TCP连接减少反复握手带来的额外开销。如果不勾选每个请求都新建连接TPS会被大幅压低对你判断系统真实性能产生严重干扰。我自己排查过很多次“性能差得离谱”的情况最后发现就是连接没复用。6.2 JMeter内存溢出与压测机性能JMeter本身是用Java写的图形工具跑大并发时会一直在内存里生成请求结果、保持测试数据。默认JVM堆内存如果只有几百MB并发数稍微上来一点就会报OutOfMemoryError: Java heap space测试直接中断。解决方法是改JMeter启动脚本里的堆内存配置。在bin目录下找到jmeter.bat或jmeter.sh里面有类似HEAP-Xms512m -Xmx512m的配置改成HEAP-Xms2g -Xmx4g具体大小取决于压测机的物理内存。内存溢出还有一种个变体压测过程中GUI界面卡成幻灯片点停止按钮半天没反应。这是JMeter图形模式在大量采样下渲染结果树和曲线图导致的。如果你要做比较正式的压测建议不要用图形界面跑而是把脚本保存成jmx文件后用命令行执行jmeter -n -t test_plan.jmx -l result.jtl -e -o report_dir这条命令的意思是以非GUI模式运行脚本把原始采样结果写到result.jtl然后在report_dir目录生成HTML可视化报告。非GUI模式不加载界面组件资源占用会小很多同样的压测机也能支撑更大的并发量。跑完之后打开report_dir里的index.html自带图表比默认聚合报告直观多了。压测机本身的性能也需要观察。如果你在笔记本电脑上一边跑1000并发一边打开浏览器看视频压测结果只会反映这台电脑的极限而不是服务器的极限。经验法则是压测机的CPU占用不要超过70%网络带宽不要打满否则先升级压测机或者改用多台机器分担压力。6.3 测试数据与脚本设计的干扰压测结果不准很多时候不是系统问题而是测试数据在捣乱。在压测环境里重复使用同一批账号可能会命中缓存、触发限流或者数据冲突。比如同一个账号被100个线程同时登录可能触发了服务端的登录锁或频率限制错误率升高但这不是系统性能问题是数据模型的问题。解决方向有三个一是数据量要足够并保持唯一能用账号密码、用户ID做参数化的就尽量参数化二是对于有状态的数据比如订单、优惠券一定要确保每个线程的数据相互独立三是在测读取型接口时最好造一批有代表性的数据比如不同价格区间、不同分类的商品避免全部命中同一个热点数据导致缓存结果失真。脚本设计上还有一个常见干扰是断言过重。每增加一个断言都增加维度如果断言写得特别复杂比如对完整响应体做全文匹配JMeter自身消耗甚至可能超过被测系统。压测时建议用最少的关键词验对错复杂校验留给功能测试去做。7. 几个实操习惯能帮你省很多时间7.1 压测前先做一场冒烟测试不管脚本写了多少步第一次跑永远从1个线程开始。这不叫保守这叫对流程负责。1个线程跑通之后把查看结果树打开仔细看响应内容确认状态码、关键返回字段、关联变量都正确再加到10个线程跑一轮确认数据参数化正常最后再改成真实压测规模。我见过太多反例脚本一写完直接上500并发结果跑了五分钟全是401仔细一看是Token没关联上或者CSV文件路径配错了每个线程都没读到数据报了满屏的错误。这些低级问题如果在1个线程阶段去查一分钟就能定位放到高并发阶段去查你会分不清是脚本问题还是系统问题排查成本翻了几倍。冒烟测试不是浪费时间它是给后面所有工作兜底。7.2 记录每一轮测试的现场环境性能测试是一个反复对比、不断定位的过程。今天跑了一轮明天改完配置再跑一轮如果不记录现场信息两轮结果出来后你根本说不清楚差异来自哪里。我个人的习惯是每轮测试前先记录脚本版本、并发数、Ramp-Up值、循环次数、压测机资源占用、被测环境标签、服务器大致配置、压测时间段。这些信息随手记在一个表格里就行。很多人觉得这很繁琐但等测试结果异常时需要回溯时你会感谢自己当时多记了这一行。性能测试本质上是一个实验过程实验不记录条件变更结论就没有可信度。这个习惯越早刻意练习越好。7.3 配合服务器监控看问题只靠JMeter的报告只是的“现象”不是“原因”。JMeter只能告诉你系统变慢了它不能告诉你为什么变慢。要回答“为什么”必须把服务器端的监控数据拉起来看。压测过程中在应用服务器上盯着CPU、内存、磁盘IO、网络带宽在数据库上盯着连接数、慢SQL、锁等待这是一套组合拳。工具上最直接的是系统自带的top、vmstat、iostat配合JVM的jstat、jmap。新手不需要一上来就上很重的监控平台先用这些命令行工具能在压测发生时看到资源变化曲线。当你发现TPS下跌的那一秒钟数据库连接数恰好逼近了连接池上限瓶颈定位就非常清楚了。如果再有一两次压测复现基本就可以确认问题然后去找开发改配置或改代码。写在最后的个人体会JMeter这个工具本身不难学花上一天时间你就能搭出第一个像样的压测脚本。但性能测试真正的困难从来不在工具操作上而在于你能否设计一个合理的测试模型能否在满屏的数据里找到真正的问题线索。我见过有人把线程组设成1000直接就压也见过有人对一个登录接口反复测了十几轮才发现数据库连接池才是瓶颈。工具只是手分析才是脑。还有一个小建议如果你刚开始学性能测试不要执着于复杂的分布式压测和花哨的插件。先把单机JMeter用好把线程组、HTTP请求、参数化、断言、关联、聚合报告这套基础链路吃透。等你能够独立完成一轮压测、能向团队清晰说明瓶颈在哪里的时候你会发现知识体系已经自己长出骨架后面那些高级功能只是在这个骨架上添砖加瓦。