JMeter+InfluxDB+Grafana:搭建性能测试实时监控看板
做性能测试的人基本都经历过这样的场景JMeter压着压着突然想知道当前的TPS到底有没有掉链子响应时间的曲线是不是已经拐头向上可日志刷得太快根本看不出来。一开始我也用JMeter自带的监听器结果压测刚跑几分钟GUI界面就卡得动不了统计曲线更是“延迟”得有模有样——压测跑完了图才慢慢出来半截。后来我把这三件套组合用起来了JMeter负责施压和采集InfluxDB负责存储时序数据Grafana负责把指标画成实时看板才真正体会到什么叫“一边压测一边盯着屏幕看曲线跳舞”。这套组合解决的核心问题很明确JMeter跑压测的时候你需要在秒级延迟内看到当前系统的吞吐量、响应时间、错误率、网络流量等关键指标变化趋势并且这些数据要能留存下来便于压测结束后复盘分析。传统的HTML报告和CSV文件只能事后看过程同步监控这件事基本做不到。这篇文章我把自己从零搭建这套监控链路的完整过程、配置参数、踩坑经验全部整理出来适合正在做接口压测、全链路压测、稳定性测试的测试工程师、测试开发以及想搭一套轻量级压测监控平台的运维同学参考照着走一遍就能把环境跑起来。1. 架构设计与组件选型思路1.1 性能测试监控到底缺什么先聊一个很多人忽略的问题为什么JMeter自带的聚合报告、jpgc插件不能满足性能测试过程中的监控需求JMeter自带监听器确实能出结果但有几个绕不开的痛点。一是结果存储方式太“平”全部数据堆在内存里跑完才落盘成CSV或JTL文件压测时间长一点内存就吃紧特别是用GUI模式跑的时候随便几百并发就开始卡顿。二是可视化能力太弱聚合报告一张静态表格线条图和TPS图只能在一个压测进程内短暂查看没法跨线程组、跨时间、跨机器汇总。三是中间过程不可控你想在压测进行到一半的时候看系统瓶颈在哪或者想从外部主动停掉部分施压机是做不到的。所以性能测试监控体系真正缺的是一个能接受JMeter实时上报数据的存储端和一个能将存储端数据实时渲染为图表的展示端。Jmeter负责采集和发送InfluxDB负责存储与查询Grafana负责展示与告警三者的边界非常清晰。这也是目前主流的压测监控组合方案基本没有太多替代品能做到这样轻量又够用。1.2 三个工具各自的分工与选型逻辑InfluxDB作为时序数据库存的就是“带时间戳的测量值”每一列数据天然带时间索引非常适合TPS、响应时间、错误率这类会随时间连续变化的数据。相比MySQL和PostgreSQLInfluxDB对高频写入做了深度优化压测过程中每秒几十甚至上百条指标写入也不会有压力查询端用类SQL的InfluxQL或Flux语法就能快速按时间窗口聚合。选版本的时候需要留意InfluxDB 1.8和2.x的使用方式差别较大1.8更简单直接开箱即用社区资料也多我推荐先用1.8入门。Grafana是数据可视化网关它本身不存任何数据只负责从InfluxDB这种数据源拉取数据然后渲染成折线图、柱状图、热力图、仪表盘等各种面板。它最大的价值在于“看板”这个抽象概念你可以把TPS、响应时间、错误率、JVM内存等几十个指标组合到一个页面里压测时投影到大屏上或者自己开个浏览器页面盯着看。JMeter侧的选择也很重要。JMeter本身并不直接对接InfluxDB需要用到Backend Listener后端监听器。JMeter从5.x版本开始内置了“influxdbBackendListenerClient”实现不需要额外安装第三方jar包配置好InfluxDB地址、数据库名、采样周期等参数JMeter就会周期性默认5秒一次把聚合指标通过HTTP接口写入InfluxDB。这套架构的部署形态也很灵活压测机和监控平台可以分开部署也可以通过nginx反代统一暴露。我个人建议Grafana和InfluxDB部署在同一台机器上JMeter可以跑在多台施压机上施压机只要把指标上报到InfluxDB的地址就行。这样就天然形成了一个压测监控的小集群不用在每台压测机上再安装任何额外的展示组件。2. 环境部署先搭起两个基础组件2.1 CentOS 7.9环境中安装JDK与JMeterJMeter本身是纯Java应用所以第一步是装JDK。JMeter 5.6.x要求JDK 8以上我个人用的JDK 8实际跑大规模压测时也可以直接上JDK 11性能差异并不大。安装JDK最稳的方式是用yum装OpenJDKsudo yum install -y java-1.8.0-openjdk-devel java -versionJMeter下载安装非常简单到官网下载tgz压缩包解压之后bin目录里就有jmeter脚本。我习惯把JMeter放到固定路径释放后做个软链方便命令行直接调用tar -zxvf apache-jmeter-5.6.3.tgz -C /opt ln -s /opt/apache-jmeter-5.6.3/bin/jmeter /usr/local/bin/jmeter jmeter --version需要提醒的是跑压测的时候千万不要用GUI模式内存占用高、非聚合数据全量缓存还会影响施压机本身的性能。正式压测一律用命令行模式后面我在第三节里会给出标准命令模板。2.2 安装InfluxDB 1.8并初始化InfluxDB的安装比想象中简单但有两个容易出错的地方系统防火墙端口以及InfluxDB的HTTP服务默认绑定地址。先配置yum源然后安装cat EOF | sudo tee /etc/yum.repos.d/influxdb.repo [influxdb] name InfluxDB Repository - RHEL \$releasever baseurl https://repos.influxdata.com/rhel/\$releasever/\$basearch/main enabled 1 gpgcheck 1 gpgkey https://repos.influxdata.com/influxdb.key EOF sudo yum install -y influxdb sudo systemctl enable --now influxdb启动后修改配置文件/etc/influxdb/influxdb.conf重点改两个地方。第一HTTP服务和匿名访问。默认HTTP服务只绑定127.0.0.1JMeter从别的机器上报数据根本连不上。打开注释并修改为监听所有网卡[http] bind-address :8086 enabled true第二留一个数据库给JMeter使用。InfluxDB初始状态下没有任何数据库需要用它的CLI工具建库并且建议同时设置保留策略避免压测数据无限增长撑爆磁盘influx CREATE DATABASE jmeter CREATE RETENTION POLICY rp_90d ON jmeter DURATION 90d REPLICATION 1 DEFAULT SHOW DATABASES这里有个细节需要注意JMeter的Backend Listener默认写库名就是jmeter所以建议直接用这个名字后面省去一堆配置不对齐的麻烦。如果你已经跑到2.x版本写法会变成用token认证和v2的API接口路径都有所不同本篇文章下方的示例均以1.8为准。2.3 安装Grafana并接入InfluxDB数据源Grafana安装同样简单官方yum源装好之后启动服务浏览器打开3000端口即可cat EOF | sudo tee /etc/yum.repos.d/grafana.repo [grafana] namegrafana baseurlhttps://packages.grafana.com/oss/rpm repo_gpgcheck1 enabled1 gpgcheck1 gpgkeyhttps://packages.grafana.com/gpg.key sslverify1 sslcacert/etc/pki/tls/certs/ca-bundle.crt EOF sudo yum install -y grafana sudo systemctl enable --now grafana-server首次登录Grafana用admin/admin会强制要求修改密码。接下来就是配置数据源左侧菜单进入Configuration然后选Data Sources点击Add data source选InfluxDB。有几个容易写错的点需要说明URL要填InfluxDB的HTTP接口地址格式是http://IP:8086不能只填IPAccess选Server默认就是Server这样所有查询都由Grafana服务器来执行浏览器只负责展示Database填jmeterUser留空或者填rootPassword也留空因为InfluxDB 1.8默认开了认证但没设密码HTTP Method选GET或POST都行建议默认GET填完点击Save test如果看到绿色的“Successfully queried the InfluxDB API”说明Grafana已经能正常从InfluxDB读取数据链路还差JMeter这一端下面的内容我们就打通它。3. 核心链路打通用JMeter后端监听器把指标送进InfluxDB3.1 编写压测脚本时的常见坑很多人在搭建这套监控时习惯用JMeter GUI模式在界面上“Add Listener Backend Listener”脚本跑起来确实能看到数据上报但这种方式只适合验证配置。真正上生产压测脚本要用命令行模式执行所以监听器的配置也应该直接写在jmx脚本里或者以jtl模板的方式复用。以我自己常用的JMeter压测脚本为例结构是一个线程组里放了两个Sampler分别是HTTP请求和JDBC请求模拟真实的混合业务场景。线程数、Ramp-Up时间、循环次数都按压测计划配置好然后Listener节点下只放Backend Listener这一项不放任何GUI监听器。这样脚本能够从命令行直接跑也不用担心JMeter自身的GC问题。需要注意的是Backend Listener支持多个实例如果脚本里有多个线程组或者有多个压测场景指标需要分别展示可以给不同的Listener起不同的名称配合InfluxDB的measurement和tag做好区分否则所有线程组的指标会混到一起。3.2 配置influxdbBackendListenerClient的参数在GUI模式里添加Backend Listener选择Backend Listener implementation为“influxdbBackendListenerClient”然后配置各项参数。下面是我验证过多次的一套参数模板直接用即可influxdbMetricsSender: org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender influxdbUrl: http://192.168.1.100:8086/write?dbjmeter application: perf_test_app measurement: jmeter summaryOnly: false samplersList: 全部采样器 useRegexForSamplersList: false percentiles: 90;95;99 expectedTags: 可不填逐一说明influxdbUrl是InfluxDB的HTTP写接口路径必须以/write?dbjmeter结尾这里不是填IP:8086就完事的application是自定义标签建议设置成被测系统名甚至带上压测批次号比如app_login_test_20250101这样InfluxDB里可以通过这个tag过滤不同批次的数据measurement对应InfluxDB里的表名默认jmeter即可percentiles定义需要统计的百分位这是评估响应时间分布的关键指标90/95/99基本是性能测试的标配。配置完成后要确保在JMeter的lib目录下能看到三个核心jar包commons-pool2、influxdb-client、jmeter-http其中jmeter-http是Backend Listener动态加载的依赖。如果手头没有这些包直接从JMeter安装目录的lib/ext下找。3.3 启动压测并用命令行验证数据落库脚本和配置准备好后用命令行启动压测jmeter -n -t perf_test.jmx -l result.jtl -e -o report_dir -j perf_test.log启动之后大概过5秒左右InfluxDB那边应该开始收到第一批数据。验证方式很简单直接在InfluxDB CLI里执行use jmeter; show measurements; select * from jmeter order by time desc limit 5;如果能返回类似下面的结果说明数据链路已经通了time application count max mean min pct90 pct95 pct99 responseTime ... 2025-01-05T12:00:05Z app_login_test 1200 852 124 23 210 268 412 124 ...这里再分享一个我常用的补充手段在InfluxDB CLI里按时间窗口查询实时TPS和响应时间可以快速判断当前压测是否达到预期目标。比如每秒进阶看吞吐量select sum(count) from jmeter where time now() - 1m group by time(10s)这种临时手查的方式适合快速排障但你要是想在压测进行中随时盯大屏还是继续往下看Grafana看板的搭建。4. Grafana看板搭建从数据到可视化4.1 配置InfluxDB数据源细节再补充上一节里已经提过数据源的基础配置这里我想把查询语言相关的配置细节补全。Grafana接入InfluxDB有两种查询能力一种是InfluxQL另一种是FluxGrafana版本的InfluxDB数据源配置里默认走InfluxQL这也是老用户最熟悉的方式。查询面板时选择“A”查询在FROM项里选择measurement为jmeterSELECT项里选择mean(count)在下方的GROUP BY里设置time(5s)、tag(application)就能生成一条时间序列图。这里有一个关键理解需要特别说明JMeter上报到InfluxDB的数据并不是按“每秒一条”存的而是Backend Listener每隔固定时间默认5秒上报一次每条记录里的count等指标是这5秒内的累计值或瞬时值。比如统计维度是“每秒请求数”实际上每个点代表这5秒内的总请求数画图时需要除以时间跨度才能得到正确的每秒吞吐量否则数值会偏大。这一点很多人第一次看曲线的时候会蒙圈所以画图时聚合周期尽量和上报周期保持一致或者直接用sum除以时间窗口计算。我实际用的TPS查询语句大致是这样的SELECT sum(count) / 5 FROM jmeter WHERE $timeFilter GROUP BY time(5s) fill(null)这里的除以5是因为上报周期是5秒如果你想改成10秒聚合就把除以5改成除以10。响应时间的查询则直接用平均值SELECT mean(mean) FROM jmeter WHERE $timeFilter GROUP BY time(5s) fill(null)4.2 导入现成看板ID还是自己搭Grafana社区有好几个成熟的JMeter监控看板导入时可以省掉大量手动配置面板的时间。在Grafana页面左侧点加号选中Import Dashboard输入看板ID拉到官方市场比较常用的是ID 5496和ID 13532前者对InfluxDB 1.x的兼容性更好后者查询方式稍激进初次使用容易因为字段不匹配报错所以我个人推荐先用5496。导入时Grafana会让你选择对应的数据源把刚才配置好的InfluxDB数据源填进去保存后看板模板就会自动生成。这个看板包含了吞吐量TPS / QPS趋势图响应时间平均值与各百分位线趋势图活跃线程数曲线错误数、错误率折线网络收发速率柱状图响应字节数的量与速率每个面板的标题下面都有一个查询编辑按钮点开后可以看到它实际用的查询语句这也是一种现成的学习样本比看官方文档更快。不过现成看板有个问题字段名对不上。比如有些看板模板里写的是“count”或“OK”但JMeter实际写入的字段可能是“count”或“errors”解析不到数据时面板就是空的。遇到这种情况我的处理办法是打开该面板的查询编辑器查看字段列表把不存在的字段改成实际存在的同名项再手动refresh一下即可。整体上我建议第一次搭建先用现成看板熟悉字段等跑过两轮压测、理解了各指标含义后再手动定制自己的核心面板比如把某些场景相关的tagapplication做成看板变量这样切换不同压测批次只需要改一次下拉选项。4.3 自定义核心面板的扩展思路除了现成看板平时用得最多的还是自定义面板特别是要把JMeter的业务指标和系统监控指标CPU、内存、磁盘IO、网络流量并排展示的场景。这套架构里我只讲了JMeterInfluxDBGrafana但Grafana本身可以同时接入Prometheus、Zabbix、Elasticsearch等多种数据源所以在同一个看板里把被测服务器的CPU曲线和JMeter的TPS曲线放一起也是常规操作。自定义面板的时候有几点经验值得分享变量一定做好。看板设置里加一个application变量值是InfluxDB中该tag的所有枚举值这样每个面板里的查询都通过$application这个变量动态过滤切换不同压测批次一键生效。具体写法是在Variable的Query里写SHOW TAG VALUES FROM jmeter WITH KEY application图例名称要可读。默认图例格子里显示的是measurement名很难分清哪条线是哪个批次的建议在面板的Legend里改成{{application}}或者直接配置别名。告警阈值合理设置。Grafana支持面板告警可以把错误率大于0.1%、TPS低于某个阈值、响应时间P99超过预估值拟合为告警项推送到钉钉、企业微信或者邮件。我在做长时间稳定性测试时就靠这套告警看夜里的波动不用一直盯着屏幕发呆。面板的时区也建议设置成UTC8否则时间轴显示出来的压测起始时间对不上北京时间复盘会非常混乱。5. 实战中容易遇到的问题与排查技巧5.1 InfluxDB端口不通或查询无数据端口不通是最常见的问题。表现是Grafana测试数据源报错或者JMeter日志里出现类似Connection refused。排查顺序先在InfluxDB服务器上执行ss -lntp | grep 8086确认服务监听的是不是0.0.0.0:8086如果是127.0.0.1说明配置文件没改对然后在压测机上执行telnet 192.168.1.100 8086确认网络通最后检查系统防火墙CentOS 7默认firewalld要放行该端口顺手还要看SELinux是否拦截。查询无数据时先排除常见坑Grafana数据源里Database填错、表名填写错、查询的时间范围不在当前时间窗口内。还有一点容易忽略JMeter上报数据使用的时区是UTC而Grafana展示默认是浏览器本地时区如果你的压测数据还没写入但时间轴显示已经是未来大概率是浏览器时区没调好。5.2 JMeter无数据上报的配置问题如果你发现InfluxDB里一个数据点都没有优先检查Backend Listener的influxdbUrl配置确认最后是不是以/write?dbjmeter结尾。很多教程里给的地址是http://ip:8086没有写write接口路径导致JMeter把数据发到了根路径InfluxDB直接返回404。另外检查JMeter日志中是否有HttpMetricsSender相关的报错常见的有401 Unauthorized说明InfluxDB开了认证但JMeter没配用户名密码。还有一种情况backend listener正常运行但数据就是没进InfluxDB关键点在于是否开启了samplersList和summaryOnly的配置。如果summaryOnly设为true那JMeter只会上报聚合指标也就是整个压测结果的总和没有实时的时间序列明细如果你需要每个sampler分别统计就要把summaryOnly设为false并在samplersList里写上采样器名称。5.3 压测数据时间线出现断档或毛刺数据断档一般发生在两个地方一是JMeter施压机长时间GC导致上报线程暂停二是InfluxDB写入出现阻塞。你可以在Grafana看板的图上明显看到曲线跳动得厉害这时候需要检查压测机JVM的GC日志和InfluxDB的慢查询日志。针对GC问题建议给JMeter启动脚本增加JVM调优参数特别是加大堆内存和回收策略比如使用G1回收器JVM_ARGS-Xms2g -Xmx4g -XX:MaxMetaspaceSize512m -XX:UseG1GC jmeter -n -t perf_test.jmx -l result.jtl如果压测已经进行到一半不想重启进程也可以临时降低上报频率比如把summaryOnly暂时打开只上报汇总数据减少InfluxDB的压力。5.4 Grafana查询慢导致看板卡顿用Grafana看板做秒级监控查询太慢是很影响体验的。常见的原因是面板查询里的聚合窗口太小比如每1秒聚合一次而压测时长已经几百分钟InfluxDB需要扫描的数据点太多。解决方案有两个把面板的时间范围选择器从“最近15分钟”改成“最近5分钟”或者把GROUP BY的时间窗口调大比如从5s改成30s。另外一个容易忽略的是InfluxDB的索引字段JMeter数据里的tag字段application、measurement是InfluxDB自带索引的但sampler名称如果写成了field而不是tag查询过滤就会慢很多。我一般建议在JMeter侧把sampler名字设置成tag具体做法是在influxdbUrl上追加extraTag或者直接用sampler名字命名tag字段。5.5 InfluxDB存储膨胀过快长时间稳定性压测InfluxDB的数据增长速度会比想象中快得多。默认配置下JMeter每5秒上报一次一天的数据大概有好几万点如果On-disk大小不是很大磁盘确实容易被打满。我在实际项目中有两个经验一是提前设置合理的保留策略上面已经建了一个90天的rp这样超过90天的数据自动清除二是适当地降低采样精度如果你只是看趋势不需要精确到秒级可以在InfluxDB查询层做降采样任务把历史数据聚合到1分钟粒度存储到另一个measurement里原始数据保留短一点即可。6. 从监控到分析这套链路的完整价值到这一步你已经拥有了一个完整的压测监控闭环JMeter出数InfluxDB存数Grafana亮数。在这个基础上再往前迈一步就是把监控数据变成可量化的瓶颈判断依据。比如你压测时从Grafana看到TPS在1000左右徘徊同时响应时间逐渐抬升CPU曲线冲到90%以上基本可以断定被测服务已经到了瓶颈。如果你看到TPS还没有饱和错误率已经开始攀升那大概率是依赖的服务出了问题比如数据库连接池被打满或消息队列堆积。这些判断拿到监控数据之前只能靠猜拿到之后就是板上钉钉的结论。从我自己的实际经验来看搭建这套链路最大的成本不在于组件安装而在于理解数据模型的差异。你用JMeter的Backend Listener上报的“count”在InfluxDB里到底是什么类型的field在Grafana里又该用什么样的聚合函数去展示这中间需要盘一下数据流转的全过程。建议第一次搭的时候不急着导入花哨的大屏看板先把一个最核心的TPS查询跑通再一点点把响应时间、错误率、线程数加进去把每个面板的查询语句都吃透。后面再遇到新场景比如压测Redis、压测消息队列、压测文件上传接口只需要复制看板然后改一下查询里的measurement名和tag条件就能复用相当省事。最后再分享一个小技巧如果条件允许尽量把InfluxDB和Grafana跑在SSD盘上IO延迟对查询性能的影响在压测监控这种高并发写入场景下非常明显。我自己改造过一次存储位置后看板刷新的响应速度几乎快了一倍尤其长时间压测回溯历史数据的时候体感差距特别大。