十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

JMeter监听器图表解读:四类图表联动定位性能瓶颈

JMeter监听器图表解读:四类图表联动定位性能瓶颈 我最早开始用JMeter做压测时最大的困惑不是脚本怎么写而是跑完之后面对一堆监听器图表不知道该看什么。聚合报告里Average才150ms但实际用户反馈就是卡TPS图上明明有高峰数据库却不忙响应时间曲线一路爬升CPU却只有30%。这些都是典型的“图表看了但没看进去”的状态。这篇博文就把我这些年分析JMeter监听器图表、定位系统瓶颈的思路完整捋一遍。内容围绕四类最常用的监听器展开聚合报告、查看结果树、TPS与响应时间趋势图、PerfMon服务端资源监控并且会结合一个真实案例讲清楚怎么从图表数据反推瓶颈到底在网络层、应用层还是数据库层。适合刚接触性能测试的测试工程师也适合那些已经能跑压测脚本但每次出报告都被问“瓶颈在哪”时答不上来的同学。1. 先搞清楚监听器在压测里的真实位置1.1 压测的本质构造压力、观察表现、反推短板很多人把压测理解成“写个脚本跑100个线程看报告通不通过”这个理解太浅了。性能测试的核心其实是一个闭环构造压力、观察表现、反推短板、验证优化。JMeter的线程组和各种Sampler负责“构造压力”而监听器负责“观察表现”。但观察表现不是简单把数据画出来而是要从这些数据里反推出系统在哪一层、哪个组件先扛不住了。我经常打一个比方JMeter本身是一辆车的数据采集仪它记录发动机转速、车速、水温但仪表亮了不代表车子报废你得判断是轮胎打滑、变速箱顿挫还是发动机气阻。监听器图表就是这些仪表瓶颈定位就是修车师傅的读表能力。所以你在配置监听器之前先要回答一个问题这一轮压测我到底想验证什么如果是验证单接口容量那重点看TPS和响应时间如果是排查线上偶发超时那重点看错误类型和长尾响应如果是全链路压测那必须配合服务端监控一起看。监听器的选择和使用应该服务于压测目标而不是跑完再对着图表猜。1.2 监听器的分类与常用图表选型JMeter的监听器从功能上可以分为三大类结果查看类、性能指标类、外部资源关联类。结果查看类最典型的就是查看结果树和断言结果主要看单个请求的响应体、状态码、断言是否通过适合排查功能性问题比如接口返回500、数据格式不对。性能指标类包括聚合报告、Summary Report、TPS曲线、响应时间曲线、连接时间曲线等这类监听器把每个采样数据汇总或按时间序列展示是定位性能瓶颈的主要依据。外部资源关联类比如PerfMon Metrics Collector配合ServerAgent可以监控应用服务器、数据库服务器的CPU、内存、磁盘、网络把“服务端资源”和“JMeter侧的吞吐/响应时间”放在同一个时间轴上比对这才是定位瓶颈的关键。选型的时候我比较收敛不建议什么监听器都往测试计划里堆。一个压测场景我通常固定放四类聚合报告看整体指标查看结果树用于调试阶段正式压测时一定关闭TPS和响应时间趋势图看变化过程PerfMon关联服务端资源。图表越多数据越杂反而不容易聚焦。2. 常用监听器图表逐个拆解2.1 聚合报告最容易误读的一张“体检单”聚合报告是出现频率最高的监听器它能给出一次压测的汇总数据包含样本数、Average、Min、Max、Std. Dev.、Error %、Throughput、Received KB/sec、Sent KB/sec以及90% Line、95% Line、99% Line等百分位响应时间。这里最大的坑是平均值不能单独看。聚合报告里的Average是算术平均值一旦系统出现少量超长响应平均值会被抬高但更危险的是平均值正常但长尾严重。举例来说某接口Average只有120ms看起来很好但99% Line到了900msMax是3.2s说明有1%的请求在1秒以上。用户访问是随机的倒霉的那1%用户就会明显感知到卡顿。所以我的习惯是先看Error %错误率为0再看Throughput然后看90%/95%/99% Line最后才看Average。判断标准也不是固定值而是波动范围。如果99% Line和Average差了好几个数量级说明系统存在明显的长尾现象常见原因有线程池排队、数据库连接等待、GC停顿、网络重传等。还有一个容易忽略的点聚合报告里的Std. Dev.标准偏差。偏差越大说明响应时间越不稳定。你看平均值120ms、标准偏差只有15ms那系统很稳如果标准偏差到了80ms说明部分请求已经显著变慢这个时候结合查看结果树或者响应时间曲线就能定位到波动发生的阶段。2.2 查看结果树排查单个请求的显微镜查看结果树应该算是最直观的监听器它能展示每个Sampler的请求数据、响应数据和响应时间。我用它主要做两件事一是在脚本调试阶段确认请求参数、Header、Cookie是否正确二是在压测中发现错误时通过响应体内容判断错误类型。但正式压测期间我强烈建议把查看结果树关掉。原因很简单它会保存每个请求的完整响应数据在高并发场景下会造成巨大的内存和IO开销直接影响压测机自身性能。说到这里想起不少同学遇到过“压测机100个线程就把CPU跑满了”的情况十有八九是开着结果树跑压测还勾选了“Save Response Data”。如果你需要保留请求明细用于排查建议用“配置结果文件”的方式把结果写入JTL文件并且只保存必要的字段。在JMeter的bin目录下修改jmeter.properties可以调整采样器结果保存项比如只需要保存时间戳、响应时间、成功标志、线程名就不要勾选响应头和响应体这样IO压力会小很多。2.3 TPS与响应时间趋势图定位瓶颈的关键曲线聚合报告给的是“一锤子买卖”的汇总数据但瓶颈往往发生在某个时间点而不是整个压测周期的平均值。所以对我而言真正有价值的图表是随时间变化的趋势图。Transactions per SecondTPS图看的是系统每秒处理的事务数。一个健康的系统在逐步加压过程中TPS会先线性增长然后到达一个平台期这个平台期就是系统当前的容量上限。如果在某个并发数下TPS出现断崖式下跌那基本可以断定某个组件被压垮了。比较典型的现象是数据库连接池被打满请求全部排队等待TPS骤降同时响应时间曲线同步飙升。Response Times Over Time图看的是采样时间点的平均响应时间变化。如果TPS维持稳定、响应时间平缓系统处于健康状态如果响应时间随时间线性爬升常见的解释是缓存命中率下降、内存持续增长导致GC频发、连接池资源耗尽后新建连接变慢。这里要注意区分“瞬时尖刺”和“持续爬坡”瞬时尖刺可能是GC或者网络抖动持续爬坡则指向资源泄漏或队列堆积。实际操作中我会把这两个图放在一起看。以我最近一次接口压测为例从100并发开始每30秒增加50并发TPS稳步从300升到850响应时间从80ms升到160ms这个阶段符合预期。当并发数加到200时TPS不再上升稳定在900左右但响应时间还在涨到了并发250时TPS掉到600响应时间到了1.2s。这时候判断就很清晰系统瓶颈从“吞吐受限”变成了“排队严重”重点去看数据库连接池和中间件线程池。2.4 连接时间图与PerfMon资源监控别只盯着应用侧很多人看完TPS和响应时间就开始下结论这是不完整的。响应时间只告诉你“慢了”但没告诉你“慢在哪”。这时要把网络连接时间、服务端资源数据拉进来。JMeter里有一个Connect Time指标在聚合报告和趋势图里都有体现。Connect Time是客户端与服务器建立TCP连接所花费的时间。正常情况下应该是毫秒级。如果你发现Connect Time持续偏高要么是网络链路本身有问题比如带宽打满、防火墙限制连接数、跨机房公网传输要么是服务端的TCP连接队列满了新的连接请求在排队这个在Linux上通常表现为TCP backlog溢出。服务端资源的监控我一般用PerfMon配合ServerAgent在目标服务器上采集指标。注意PerfMon不是只看CPU。CPU高不是坏事坏的是CPU高且TPS上不去说明应用在空转或者锁竞争CPU低但TPS上不去常见原因在锁等待、数据库慢查询、外部依赖调用超时。内存指标要看是不是存在持续增长和GC波动磁盘要看util和await时间网络要看带宽是否打满。这里给个简单的判断参考现象可能原因下一步看什么TPS上不去CPU 90%应用逻辑计算密集或线程竞争激烈线程Dump、火焰图TPS上不去CPU 40%不到瓶颈不在应用CPU而在IO/锁/远程调用数据库监控、中间件连接池、外部依赖响应时间间歇性飙高GC停顿、定时任务抢占资源GC日志、PerfMon的CPU曲线Connect Time持续增长网络问题或TCP队列满抓包、服务端netstat队列3. 图表联动定位瓶颈的实操套路3.1 不同压测场景的关注点差异不是所有压测都用同一套图表解读方式。我在日常工作里会把压测场景分成三类关注点完全不同。容量验证的场景比如“系统能不能支撑双十一的峰值流量”重点看TPS在目标并发下能不能达标响应时间是否在SLA范围内同时关注错误率。这个场景下聚合报告和TPS平台期最有价值。稳定性压测的场景比如“系统跑8小时会不会内存泄漏”要盯着趋势图看重点关注响应时间是否在缓慢爬升、TPS是否在缓慢下降、内存曲线是否逐步走高。如果能在趋势图上看到阶梯式上升那你该去查缓存淘汰策略、慢SQL积累和连接池回收机制了。故障排查类压测比如“线上反馈每天下午3点开始卡顿”这需要先构造接近线上的并发模型然后通过查看结果树和连接时间把故障时刻的分布定位到具体请求和具体时间段。这种场景通常要结合日志系统一起看JMeter图表提供的是客户端视角的证据。3.2 分层排查法从客户端到数据库逐级拆解定位瓶颈本质上是在回答“时间都花在哪了”。我总结了一个五层排查法客户端层、网络层、接入层、应用层、数据层。客户端层看的是JMeter自身有没有成为瓶颈。比如压测机CPU跑满网络带宽占满那后面的所有数据都是无效的。这个可以通过查看压测机的资源占用发现。网络层看Connect Time和发送/接收字节数如果连接时间高、带宽指标接近上限优先查网络链路。接入层和中间件层看PerfMon里的连接数、线程池活跃线程、队列深度。数据层看数据库连接数、慢查询数、锁等待时间、缓冲池命中率。操作上我是这样做的跑一轮压测先把JMeter、应用服务器、数据库三端的监控数据时间轴对齐。发现响应时间上涨时直接把PerfMon曲线打开看是应用服务器CPU先涨还是数据库连接数先涨还是网络指标先变化。谁先变化瓶颈大概率就在谁的链路上。3.3 一次典型瓶颈定位的完整复盘说一个我印象很深的案例。被测是一个登录接口测试脚本是100个线程Ramp-Up 60秒循环压测10分钟。第一轮结果聚合报告显示Average响应时间180msError %只有0.3%Throughput稳定在650左右但99% Line到了980msMax接近3s。从聚合报告看系统“还能用”但长尾很明显。我打开TPS趋势图发现从第4分钟开始TPS从680缓慢下降到620响应时间曲线从150ms涨到600ms。PerfMon上应用服务器的CPU只有35%内存曲线平稳但数据库连接数从40涨到了120并且持续处于高水位。这时候问题基本聚到数据库连接上。我去看数据库端的慢查询日志发现一个根据用户名查用户信息的SQL在连接数升高后执行计划从索引扫描变成了全表扫描单次执行时间从10ms涨到300ms。根本原因是数据量涨到一定程度后索引统计信息没有更新优化器选错了执行计划。后续做法是更新统计信息并给关联表加了组合索引复测后99% Line降到了180msTPS稳定在700左右。这个案例里如果只盯着聚合报告看Average永远不会发现问题因为平均值被大多数正常请求给“稀释”了。反而是TPS趋势图、连接数曲线和慢查询日志的组合把问题一层层剥了出来。3.4 别让参数化和断言毁掉你的图表有相当一部分“瓶颈”不是系统的问题而是脚本本身的问题。最常见的就是参数化设置不当。比如压测登录接口如果你把同一个用户名密码在所有线程里共用那数据库的行锁和缓存热点会让响应时间和TPS看起来异常但这不是系统容量问题是数据倾斜问题。CSV Data Set Config里的Sharing Mode很关键它决定参数在不同线程之间怎么分配。All threads模式下每个线程从头开始读取数据多线程之间可能读到相同值Current thread group则让参数平均分给当前线程组里的线程Current thread是每个线程单独一个游标。我曾经遇到过“每个线程分块取值”的需求其实就是用Current thread模式让每个线程各读各的一段数据这样测试数据不会互相干扰压测曲线也会平滑很多。断言同样会影响图表。如果你在Sampler下加了一个BeanShell断言里面写了一段很重的字符串处理逻辑那么JMeter自身的处理时间会被计入采样时间测得的结果根本不是接口的真实响应时间。我的习惯是能用响应断言解决的不用JSON Extractor能用JSON Extractor的不用BeanShell。断言写得太重压测机的CPU会先被拖垮这个锅不该让被测系统背。4. 常见问题与排查技巧实录4.1 跑完压测监听器没有数据输出怎么办这个问题经常发生尤其是刚接触JMeter的同学。你老老实实跑完脚本打开监听器一看面板上要么全是空的要么只有最后一段数据。先检查监听器放在哪个位置。监听器放在线程组外面并且测试计划里有多个启动方式时有时会因为配置问题导致没有绑定到采样结果。更常见的原因是你用了命令行压测模式jmeter -n -t xxx.jmx但没有配置结果文件输出或者打开的是新开的GUI没有加载JTL结果文件。命令行模式跑完后结果都在.jtl文件里你需要把原来的监听器指向这个文件或者新建一个测试计划用“浏览”按钮把JTL导入查看。还有人会问“监听器未启动”是怎么回事。这里大概率是把Jmeter的监听器概念和Oracle数据库的TNS监听器搞混了。Oracle报ORA-12514: TNS: listener does not currently know of service requested in connect descriptor这个“监听器”是数据库服务端用来接受客户端连接的进程不是JMeter的组件。遇到ORA-12514要去看Oracle监听器配置文件里的SERVICE_NAME和连接串是否匹配和JMeter没有关系。这个虽然不属于JMeter图表分析但确实很多人被这个检索词误导过。4.2 HTTPS脚本录制和证书导致的“伪失败”用JMeter录制HTTPS脚本时会碰到证书问题。默认情况下JMeter生成的是自签名证书如果被测系统做双向认证或者客户端校验证书链脚本就会报SSL握手失败。这种失败不是服务端性能问题也不是脚本逻辑问题而是证书不被信任导致的。解决办法在JMeter的安装目录下执行bin/openssl或者直接通过系统工具生成证书将ApacheJMeterTemporaryRootCA.crt导入被测系统的可信证书库。另外一种思路是完全不用录制直接手动编写HTTP Sampler把HTTPS的证书校验关掉在JMeter的bin目录下修改jmeter.properties设置https.default.protocolTLSv1.2或者在使用HTTP Request时勾选“Use KeepAlive”并添加HTTP头管理器。即使证书问题解决了也要注意HTTPS脚本和HTTP脚本在压测结果上的差异。TLS握手会带来额外的CPU消耗和连接建立时间如果你的压测目标是评估应用逻辑性能建议开启KeepAlive并在脚本里提前做一次预热请求把握手开销排除在统计之外。4.3 吞吐量上不去、资源又不饱和的典型场景我接触过不少团队压测遇到最困惑的现象是TPS就是上不去但CPU、内存、网络全都低得很。这种“四不像”的状态排查方向不要盯着服务器资源而是要从“请求是否真的并发”倒推。一种可能是不合理地使用了全局锁或者分布式锁。应用层看起来没占多少CPU但线程都在锁上排队。这种情况看线程Dump最直接能看到大量线程处于BLOCKED或者WAITING状态。另一种可能是数据库连接池配置太小。应用服务器CPU很低数据库连接数却到了上限新的请求拿不到连接只能在应用层等着。这个场景里JMeter侧的表现就是响应时间逐渐升高、TPS平台很低但应用服务器资源空闲。解决办法不是无脑调大连接池而是要做数据库端的慢查询和锁等待分析确认是SQL本身慢还是连接复用不足。还有一种非常容易被忽略的情况压测机本身的端口资源耗尽。尤其是短连接压测客户端每次建立新连接TIME_WAIT状态的socket越积越多最后新的TCP连接无法建立表现在图表上就是Connect Time飙高、错误率上升。这个时候去调服务端一点意义都没有应该调整压测机的tcp_tw_reuse、tcp_fin_timeout参数或者改用长连接。4.4 断言和前置脚本写得太重结果失真前面提到BeanShell断言的问题这里再展开一下。JMeter 4.x以后BeanShell组件的性能其实并不理想官方和社区都更推荐JSR223 Groovy。如果你在脚本里用了大量BeanShell定时器、BeanShell断言在高并发场景下这些脚本的执行时间会叠加到采样结果里。我见过一个极端案例接口本身响应时间只有50ms但因为有一段BeanShell断言做了复杂的JSON解析和字符串替换测出来的Average直接变成了400ms。定位这种问题有一个很简单的办法单独压测依次禁用Sampler下的断言、后置处理器、定时器对比TPS和响应时间变化。如果禁用后指标大幅改善那恭喜你问题出在压测脚本自己身上而不是被测系统。4.5 二次压测时一定要清理历史数据这个细节看起来小但很容易踩坑。Jmeter的聚合报告和趋势图默认是追加数据不是覆盖数据。如果你上一轮压测跑了10分钟修改脚本后直接再点一次开始图表上会把两轮数据混在一起Mean、Percentile全被拉偏。我的做法是每轮压测前右键监听器选择“Clear All”清空已有数据或者直接使用不同的结果文件名输出再通过导入外部文件的方式查看特定一轮的结果。命令行压测时用-f参数强制执行结果文件覆盖避免旧的JTL残留在目录里分析时误把上一轮的缺口数据当成这一轮的异常。5. 最后分享几个长期有用的实操习惯用到后面你会发现监听器图表分析不是一门“看图学”的技术而是“背景知识和现场数据交叉验证”的经验活。有几个习惯是我长期坚持下来的对提高定位效率帮助很大。第一每次压测前固定场景参数并记录到备注里。线程数、Ramp-Up时间、循环次数、压测机环境、被测服务版本这些信息都记录清楚。没有场景参数任何一张图表都很难解读过两周回看数据你根本不知道当时压的是什么配置。第二跑完压测后不要急着关掉先截全图。把聚合报告、TPS曲线、响应时间曲线、PerfMon资源图四张图放在同一个时间窗口截图保存命名规则带上日期和场景编号。后面写性能测试报告或者复盘线上故障时这些截图比任何文字都直观。第三不要迷信单一监控工具。JMeter的监听器只负责展示“客户端视角”的数据服务端的真实运行状态需要配合系统监控、数据库慢查询、中间件日志、GC日志来看。每次压测前花两分钟确认监控链路是否完备比事后花两小时找数据要划算得多。第四图表里的异常值不要轻易忽略也不要过度放大。一次500ms的尖峰可能只是JIT编译或网络抖动但如果尖峰出现的频率随并发数上升而增加那背后一定有一个可解释的系统行为。带着“为什么”去看图表你才能真正从“看懂了”变成“看透了”。
返回列表