资讯动态

JMeter压测实时监控:Prometheus+Grafana大屏搭建全指南

发布时间:2026/10/18 7:18:11 来源:尧图企业网站定制
做性能压测的朋友应该都有过这种体验脚本跑起来了并发线程一拨一拨地往服务器打屏幕上却只有JMeter那个滚动的日志栏想知道当前QPS到底多少、错误率涨没涨要么靠猜要么等压测结束再去看聚合报告。压测一旦跑到半小时以上中间的性能拐点基本就是一片盲区。后来我把JMeter的指标接入了Prometheus再用Grafana拉成实时大屏压测开始后几秒钟QPS、响应时间、错误率全都一目了然。这篇内容把整套监控方案从原理到配置完整写一遍包括插件参数、Prometheus采集配置、Grafana面板查询和几个容易踩的坑适合正在做接口压测、容量评估的测试开发同学直接照着复现。1. 为什么压测做了还非得再搭一套监控1.1 JMeter自带报告体系的三个硬伤先说JMeter原生的聚合报告。它确实能给出请求数、平均响应时间、错误率、吞吐量这些经典统计但它最大的问题是所有数据都是事后汇总——压测跑到第40分钟才出现错误率飙升你要等压测跑完才能从报告里看到那个过程。可性能问题最值钱的信息恰恰是“从哪个时间点开始恶化”不是“最终数值是多少”。单单这一点就足以让聚合报告在长时间压测场景里显得鸡肋。第二个硬伤是JMeter的并发模型和数据展示之间天然存在信息差。压测过程中线程组是动态调整的活动线程数、瞬时吞吐量、队列积压这些过程指标原生界面里基本没有直观的呈现方式。你可能开着jconsole去看服务端JVM又开着另一个窗口刷JMeter日志来回切换的体验很糟糕。第三个硬伤是分布式压测。你用3台执行机一起跑压测聚合报告确实会把数据汇总到控制机但如果某一台机器所在网络的延迟特别高、某一台机器的CPU被压满你从汇总表里只能看到一个“平均值被拉高”的结果根本看不出来是哪一台机器拖了后腿。这种粒度问题原生工具链很难回答。所以结论很直接压测这种动态过程需要的是和系统本身一样的实时监控能力数据要按时间线连续记录指标要能自由叠加和拆分。这恰恰是时序监控平台擅长的事。1.2 实时监控链路解决的实际问题把JMeter指标接入Prometheus之后最直观的变化就是“压测过程不再是黑盒”。你可以盯着Grafana大屏观察吞吐量的走势配合服务端监控一起看能随时回答几个以前特别难回答的问题第一错误率是缓慢上涨还是一下子冒出来的如果曲线在第12分钟突然跳变说明那个时间点有部署、有开关切换或者有并发触发了某条慢路径。只看聚合报告你连这个时间点都定位不到。第二响应时间P95和P99的拐点在哪性能压测里我经常看到的情况是平均响应时间一直很平稳但P95在第20分钟开始明显上扬说明部分请求已经被拖慢只是还没明显拖累平均值。这种“长尾变差”只有时间序列数据才能看清楚。第三能不能自动止损配合Prometheus的告警规则错误率一旦超过阈值就触发通知人不用一直盯屏幕压测翻车也能第一时间介入。对长时间稳定性压测来说这个能力比任何报告都实用。1.3 监控后端选型为什么是Prometheus而不是InfluxDB其实JMeter官方就自带Backend Listener默认支持InfluxDB、Graphite几种后端很多教程都在推“JMeter InfluxDB Grafana”的组合。这套方案一样能做实时展示那为什么我更推荐Prometheus对比一下就清楚了。对比项JMeter InfluxDBJMeter Prometheus数据接入官方Backend Listener原生支持开箱即用需要装社区插件多一步配置指标模型自定义字段查询用InfluxQL/Flux统一的指标标签模型标准PromQL标签维度支持有限拆分维度要写入时约定天然支持多维标签按标签聚合非常方便告警能力依赖Grafana告警或外部组件Prometheus内置告警规则生态成熟与业务监控融合通常是独立一套环境和业务、中间件等监控共用一套数据源运维成本需要维护InfluxDB集群和存储策略Prometheus单机就能跑存储模型简单如果你所在团队已经有了一套Prometheus监控体系比如基础监控、业务监控都在用那JMeter指标接入Prometheus就能变成这套体系里新增加的数据源而不是再维护一套新的监控存储。这一点在生产环境里省下的运维成本非常可观。再加上Prometheus的拉模式天然适合多实例部署压测执行机扩容时只需要多配几个target不用额外处理数据写入的权限和认证问题。2. 方案选型拉模式与推模式的核心原理2.1 两种接入模式的数据流差异社区里做JMeter Prometheus集成主流方式是通过一个开源的Prometheus Backend插件。这个插件内部实现了两种工作模式理解它们之间的差别配置时才不会选错。拉模式Pull插件在JMeter进程内启动一个HTTP服务默认监听9270端口把压测数据以Prometheus标准格式暴露在/metrics路径上。Prometheus按配置好的间隔比如15秒主动发起HTTP请求抓取数据。整个过程像物业每月上门抄水表水表放在JMeter进程这个房间里抄表员按时来读。推模式PushJMeter把指标数据POST到独立的Pushgateway服务上Pushgateway把数据暂存起来Prometheus再从Pushgateway端点上抓取。流程像是小区门口设了个代收点各家自己把数据送过去抄表员只从代收点取数。这两种模式对应完全不同的使用场景。拉模式最适合长时间持续的压测任务因为JMeter进程一直活着数据持续暴露Prometheus每次来都能拿到最新指标。推模式则适合短时任务——比如只跑1分钟的单接口冒烟测试假如用拉模式可能第一次抓取还没发生任务就结束了指标就丢了而推模式在任务结束前就把数据提交到了PushgatewayPrometheus之后什么时候抓都能抓到。2.2 指标类型与命名约定的基础知识为了后面配置Grafana面板时不迷糊这里简单梳理一下Prometheus的指标模型。Prometheus把数值指标分成几种类型最常见的是Counter计数器、Gauge仪表值和Histogram直方图。Counter只能单调递增适合累计型数据比如总请求数、总错误数查询时一般配合rate()函数换算成每秒变化速率。Gauge则反映当前状态可高可低比如当前活跃线程数、当前堆内存使用量。Histogram用来统计分布情况适合记录响应时间这种本身就带分布特性的数据查询时用histogram_quantile()算分位数。基于JMeter的Prometheus Backend插件暴露出来的指标前缀一般为jmeter_job常见的指标包括jmeter_job_requests_total总请求数Counter类型jmeter_job_errors_total总错误数Counter类型jmeter_job_responsetime_avg平均响应时间Gaugejmeter_job_responsetime_p50、jmeter_job_responsetime_p90、jmeter_job_responsetime_p95、jmeter_job_responsetime_p99各种分位响应时间Gaugejmeter_job_throughput实时吞吐量Gaugejmeter_job_active_threads活跃线程数Gauge需要提醒的是不同插件版本的指标命名会有细微差异。配置Grafana面板之前建议先执行一次curl http://localhost:9270/metrics在原始输出里确认当前插件实际暴露的指标名再照着写PromQL否则很容易出现“面板白屏但Prometheus里明明有数据”的情况。2.3 为什么默认优先选拉模式我自己的经验是除非压测任务短到一分钟以内否则一律用拉模式。原因有三一是拉模式少一个中间组件。Pushgateway本身是单点它挂了指标就断了还多一个服务要维护。拉模式下只要JMeter和Prometheus之间网络可达数据链路就是完整的排障路径也短。二是拉模式的数据更加“原生态”。Prometheus直接连到JMeter进程上抓取样本的采集时间戳就是真实时刻走Pushgateway的话数据的时间戳是JMeter推送那一刻中间多了转手的延迟对精细分析不太友好。三是多实例扩展方便。压测加了一台执行机只要在Prometheus的scrape_configs里加一个target就行每个实例的指标自动带上instance标签Grafana面板上随时可以按实例拆分。走Pushgateway的话反而要小心不同实例的指标在同一个job标签下互相覆盖。3. 从零配置插件、采集器、可视化三步走3.1 组件版本与基础环境准备先明确本次要用的组件版本建议JMeter尽量用5.4以上版本Prometheus用2.4x以上版本Grafana用9.x或10.x、11.x都可以。这些版本之间的兼容性目前都验证过直接跑通没有问题。我习惯用Docker Compose把Prometheus和Grafana一次性拉起。新建一个工作目录比如jmeter-monitor写一个docker-compose.ymlversion: 3.8 services: prometheus: image: prom/prometheus:latest container_name: prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro ports: - 9090:9090 restart: unless-stopped grafana: image: grafana/grafana:latest container_name: grafana ports: - 3000:3000 depends_on: - prometheus restart: unless-stopped # 只有使用Pushgateway模式时才需要这个服务 pushgateway: image: prom/pushgateway:latest container_name: pushgateway ports: - 9091:9091 restart: unless-stoppeddocker compose up -d起来之后Prometheus对应9090端口Grafana对应3000端口。Pushgateway那一段如果你确定只用拉模式直接删掉或者注释掉都行留着也不影响什么。3.2 JMeter插件安装与Backend Listener参数配置JMeter这边需要一个Prometheus Backend插件。安装方式有两种一是通过JMeter的Plugins Manager搜索“jmeter-prometheus-plugin”直接安装二是手动下载插件的jar包放进JMeter的lib/ext目录然后重启JMeter。手动安装后可以在“选项 → Plugins Manager”的Installed页签里确认插件已经生效。插件装好之后在测试计划上添加一个监听器右键测试计划 → “添加” → “监听器” → “Backend Listener”。在实现的类名里选择Prometheus相关的实现类类名选对之后下方会冒出一大串Key-Value形式的参数。核心参数按下面这张表设置参数含义建议值prometheus.listen.address插件内置HTTP服务的监听地址0.0.0.0prometheus.listen.port监听端口9270prometheus.metrics.endpoint指标暴露路径/metricssummary.interval.seconds指标汇总周期单位秒5collect.plugin.types采集的插件类型ALL参数释义需要多说两句。prometheus.listen.address填0.0.0.0是为了让其他机器上的Prometheus也能访问到。如果JMeter和Prometheus在同一台机器填127.0.0.1也行但分布式压测时最好保持0.0.0.0。summary.interval.seconds决定插件每隔几秒刷一次聚合指标建议和Prometheus的scrape_interval保持同一个量级或者更小一些否则面板上的曲线会显得很“钝”。注意插件的HTTP服务是随测试计划运行才启动的。压测没启动时你去访问9270端口会得到“连接被拒绝”。这是正常现象别误判成配置问题。配置完这些参数启动一个最简单的压测脚本然后手动验证一下curl http://127.0.0.1:9270/metrics如果返回的文本里出现了jmeter_job_前缀的指标说明插件已经在正常工作可以把IP改成JMeter所在机器的局域网地址再验证一次确认外网可访问。3.3 Prometheus采集配置与Target验证Prometheus端需要在工作目录下新建一个prometheus.yml。我的基础配置长这样global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: jmeter metrics_path: /metrics static_configs: - targets: - 192.168.1.100:9270 labels: scenario: login-flow注意几个细节。global.scrape_interval默认是15秒如果你把插件的summary.interval.seconds设成5秒建议这里也改成更短的抓取间隔比如10秒甚至5秒减小数据粒度误差。targets里写JMeter机器上的实际IP和插件端口不要写localhost除非你能保证Prometheus和JMeter永远部署在同一台机器。配置写好后重启Prometheus容器让配置生效。打开Prometheus自带的界面位置在http://prometheus服务器地址:9090进入“Status → Targets”页面。这里能看到名为jmeter的jobEndpoint那一列显示UP就说明抓取链路已经通了。还可以顺手用PromQL验证一下数据确实进来了。在Prometheus的Graph页面输入jmeter_job_requests_total点Execute能看到一串带时间标签的数值返回基本可以确认数据管道全通。3.4 Grafana数据源与监控面板的搭建Grafana这边配置很简单进入界面后左侧菜单“Connections → Data sources”添加Prometheus类型的数据源URL填http://prometheus:9090。因为是用Docker Compose一起跑的直接用服务名prometheus可以访问到填IP也可以只要别填localhost就行。数据源加好后有两个方向搭建面板。一个是直接导入社区现成的JMeter仪表盘在“Dashboards → New → Import”里搜索JMeter关键词找下载量高、近期有更新的模板导入改一下数据源就能用。另一个是自己手动建空白面板自由度更高也更不容易出现“模板里的指标名跟插件不匹配”的尴尬。手动建面板时我最常加的几个查询如下。每分钟吞吐量QPSsum(rate(jmeter_job_requests_total[1m])) by (instance)错误率sum(rate(jmeter_job_errors_total[1m])) by (instance) / sum(rate(jmeter_job_requests_total[1m])) by (instance) * 100P95响应时间jmeter_job_responsetime_p95当前活跃线程数jmeter_job_active_threads建议把QPS和错误率做成时间序列图把P95做成Time series或Stat面板活跃线程数做成Stat面板一眼扫过去就能掌握压测的整体状态。如果压测场景有好几个可以在Dashboard设置里加一个变量比如label_values(jmeter_job_requests_total, scenario)这样面板顶部会出现一个下拉框用来切换不同场景的曲线非常方便。3.5 分布式压测与多执行机的监控粒度分布式压测场景下Backend Listener默认运行在控制机进程里聚合的是所有执行机回传的样本最终暴露出来的指标是全量汇总视角。这个视角对整体趋势判断够用但满足不了“定位某台执行机异常”的需求。如果希望每台执行机的状态也能独立呈现有两个思路。简单一点的是在Prometheus的scrape_configs里把每台执行机的JMeter机器地址都配置成target用instance标签区分数据链路还是一样的只是多抓几个目标。复杂一点的是在每台执行机上单独部署一套采集方案把执行机自身的CPU、内存、网络也纳入监控。第一种方式更适合排查“哪台机器出的结果比较慢”这类问题第二种方式则适合判断“执行机本身是不是已经成为了瓶颈”。多target配置示例scrape_configs: - job_name: jmeter metrics_path: /metrics static_configs: - targets: - 192.168.1.100:9270 - 192.168.1.101:9270 - 192.168.1.102:9270 labels: scenario: login-flowGrafana面板上用了by (instance)聚合之后每条曲线会自动按IP拆开哪台执行机掉队一眼就能看出来。4. 常见问题与排查技巧实录4.1 指标没出来端口不通怎么定位最典型的故障就是测试计划明明在跑Prometheus的Targets页却显示DOWN或者curl直接连接失败。这时候先别急着改配置按下面顺序排查。首先确认JMeter进程真的在运行。插件服务只在测试计划运行期间监听端口压测停了端口就关了这在前面强调过。然后执行netstat -ano | findstr 9270Windows或ss -lntup | grep 9270Linux看端口是否存在如果JMeter在远程机器上还要检查系统防火墙是否放行了TCP 9270端口。提示改完prometheus.listen.port之后Prometheus里的target配置、系统防火墙规则需要同步改。经常有人只改了插件端口忘了改Prometheus配置导致怎么调都是DOWN。4.2 Prometheus显示UP但Grafana没数据Targets显示UP只说明抓取链路是通的不代表数据就到达了Grafana。这类问题大部分出在指标名或标签匹配上。先在Prometheus的Graph页面直接执行jmeter_job_requests_total能出数据的话问题就在Grafana这边——检查查询语句里的指标名是否拼写正确检查面板右上角的时间范围是否拉到了“最近15分钟”之后检查变量筛选条件里的标签值是否真实存在。有一个我踩过多次的坑Grafana面板用了scenario标签做变量但Prometheus抓取的JMeter指标里有几台老执行机的标签集合里根本没有这个标签。变量筛选会把没有该标签的序列直接过滤掉表现出来就是某些实例的曲线在面板上凭空消失数据源里查却是好的。4.3 多场景并发跑的时候数据互相污染同时跑两个压测场景比如登录场景和下单场景时如果不做标签隔离所有数据打向同一个job_name和同一批instanceGrafana面板就会串数据。解决办法是在JMeter的Backend Listener里通过自定义标签区分场景同时在Prometheus的static_configs.labels下补充场景标识字段比如上面示例里的scenario: login-flow。查询时所有PromQL都带上这个标签作为过滤条件才能保证每个场景看到的是自己的指标。4.4 Pushgateway模式下的数据不更新问题如果你选了推模式指标长时间不更新先看Pushgateway自己的http://pushgateway服务器:9091页面。打开后能看到当前暂存的所有指标组检查JMeter是否真的推送成功如果只有旧数据那就是JMeter到Pushgateway的网络或认证配置有问题。Prometheus侧则要确认scrape_configs里加上了Pushgateway的target并且路径用的默认/metrics。Pushgateway还有一个隐蔽坑任务结束后如果不手动清理旧指标会一直留在Pushgateway里下次跑压测时新老数据叠加在一起面板数值明显偏高。建议在压测脚本的teardown阶段调用Pushgateway的删除接口清理分组数据。4.5 版本兼容性与插件加载异常插件在JMeter的Backend Listener下拉列表里不出现常见原因有三个插件jar包没有放进lib/ext目录、JMeter没重启、JDK版本不匹配。插件比较老的情况下高版本JDK会抛NoSuchMethodError之类的异常。查看jmeter.log里有没有异常栈基本就能定位。注意如果一台机器上同时跑了多个JMeter实例所有实例都用同一个9270端口会冲突。要么给每个实例分配不同端口要么用Docker容器隔离网络端口映射否则只有一个实例能正常暴露指标。我把这次配置过程中的常见现象和解决方案整理成了一张速查表方便排查时对照现象最可能的原因最快的验证方法解决方向Target显示DOWN插件端口没监听curl http://JMeterIP:9270/metrics确认压测在跑、放行防火墙端口能通但没有jmeter_job指标插件汇总周期未到等几秒再刷一次检查summary.interval.seconds配置Grafana面板白屏指标名写错或时间范围不对在Prometheus Graph先跑一次原始查询对照/metrics实际输出修正查询多场景数据串线缺少标签隔离看原始序列里标签值是否唯一在targets和查询里都加上场景标签Pushgateway数据不更新JMeter和Pushgateway不通打开Pushgateway Web页面看暂存数据检查地址、网络、认证配置最后再分享一个我很受用的扩展技巧监控大屏搭好之后一定要顺手把告警规则加上。Prometheus配置里加一段告警规则错误率超过1%维持2分钟就触发警告配合Alertmanager把它推到即时通讯工具上压测期间人就可以不用一直盯着屏幕了。这段配置本身不复杂groups: - name: jmeter-alerts rules: - alert: JMeterErrorRateHigh expr: sum(rate(jmeter_job_errors_total[2m])) / sum(rate(jmeter_job_requests_total[2m])) 0.01 for: 2m labels: severity: warning annotations: summary: JMeter压测错误率超过1%我自己用下来最大的感受是这套链路搭好之后最值钱的不是那些花花绿绿的面板而是逐渐养成了“看数据找拐点”的习惯。压测跑到某一分钟时P95突然上扬能立刻判断是哪类请求、哪台执行机出了问题排查时间从十几分钟压缩到一两分钟。希望这份配置指南也能让你的压测过程不再等于盲试。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑