1. 项目概述与核心价值
最近在做一个电商大促活动的全链路压测,压到一半,团队里负责业务的同事跑过来问:“现在系统扛得住吗?TPS是多少?错误率有没有飙升?”我盯着JMeter那个黑乎乎的聚合报告和一堆不断滚动的日志,一时语塞。传统的JMeter测试报告是静态的、滞后的,你很难在压测进行时,给团队一个直观、实时、全局的性能健康视图。这就像开车只看后视镜,无法预知前方的路况。正是这个痛点,促使我花时间搭建了一套“JMeter+Grafana+Influxdb”的可视化性能测试监控平台。
简单来说,这套平台的核心工作流是: JMeter作为压力发生器,在压测执行时,将实时的性能数据(如响应时间、吞吐量、错误率)推送到InfluxDB时序数据库中进行存储;Grafana则作为数据可视化前端,从InfluxDB中查询数据,并绘制成直观、美观、可实时刷新的监控仪表盘。 这样一来,在压测过程中,所有相关人员(开发、测试、运维、产品)都可以通过一个共享的网页链接,看到如同“飞机驾驶舱”一样的实时性能仪表盘,对系统状态一目了然。
这套组合的价值远不止“好看”。首先,它实现了 测试过程的可观测性 ,你能实时发现性能拐点、资源瓶颈和异常波动,而不是等测试结束后再分析冰冷的报告。其次,它极大地 提升了团队协作效率 ,统一的视图避免了信息差和重复沟通。最后,它 为性能基线管理和趋势分析 打下了基础,历史数据得以留存,方便进行版本迭代前后的性能对比。无论你是测试工程师、开发工程师还是运维工程师,掌握这套平台的搭建,都能让你在性能工程领域的能力提升一个档次。
2. 平台架构设计与组件选型解析
2.1 为什么是JMeter+Grafana+InfluxDB?
在动手之前,我们先拆解一下为什么这三个工具是黄金组合,以及有没有其他备选方案。
JMeter
:作为压力源,它是开源、成熟、社区生态极其丰富的性能测试工具。其
Backend Listener
组件可以方便地将采样器结果发送到各种后端,包括InfluxDB。虽然像
k6
、
Locust
等现代工具也支持输出到时序数据库,但JMeter在协议支持广度(HTTP、JDBC、JMS、TCP等)、测试场景编排(逻辑控制器、断言、前置/后置处理器)以及庞大的插件生态方面,目前仍具有不可替代的优势,尤其适合复杂业务场景的模拟。
InfluxDB
:专为时序数据而生。性能测试产生的数据(时间戳、指标值)正是典型的时序数据。相比传统关系型数据库(如MySQL),InfluxDB在写入速度、数据压缩率和时间范围查询效率上有着数量级的优势。它的数据模型(Measurement, Tag, Field)也非常适合存储性能数据。例如,我们可以将一次HTTP请求作为一个数据点,其标签(Tags)可以是
transaction=Login
(事务名)、
status=200
(状态码),字段(Fields)可以是
responseTime=150
(响应时间,单位ms)、
success=1
(是否成功)。这种结构既方便按维度聚合(如查看所有登录事务的响应时间),又高效存储。
Grafana :数据可视化的王者。它支持多种数据源(包括InfluxDB),通过丰富的面板(Graph, Stat, Table, Heatmap等)和灵活的查询编辑器,可以几乎无代码地构建出专业级的监控仪表盘。其告警功能虽然在此次搭建中不是核心,但为后续的自动化监控预留了扩展性。相比自己用前端图表库开发,使用Grafana能节省大量开发和维护成本。
注意 :网上有些教程会提到使用
jmeter.influxdb插件或更早的Backend Listener实现。这里强烈建议使用JMeter 5.0及以上版本自带的Backend Listener并选择InfluxDBBackendListenerClient实现。这是Apache官方维护的实现,与InfluxDB 1.x和2.x的兼容性更好,配置也更标准化。
2.2 整体数据流与部署模式
整个平台的数据流向非常清晰:
- 数据生成 :JMeter启动压测线程,模拟用户请求。
-
数据采集与推送
:每个采样器(Sampler)执行后,
Backend Listener将结果(可配置包含哪些指标)转换为Line Protocol格式,通过HTTP API发送到InfluxDB。 - 数据存储 :InfluxDB接收并存储这些数据点。
- 数据查询与展示 :Grafana配置InfluxDB为数据源,编写查询语句(InfluxQL或Flux),将数据渲染成图表并展示在Dashboard上。
部署模式上,对于中小团队或个人学习, 将所有组件部署在同一台性能较好的机器上 是最简单的。但需要注意,JMeter压测本身会消耗大量CPU和内存(尤其是并发数高时),InfluxDB在高数据写入速率下也需要足够的I/O和内存。因此,在生产级压测中,建议将 JMeter压力机、InfluxDB数据库、Grafana服务进行分离部署 ,以避免资源竞争,确保监控数据采集的稳定性。本次搭建以单机部署为例,便于理解和快速上手。
3. 核心组件安装与基础配置
3.1 InfluxDB 1.8 安装与启动
我们选择InfluxDB 1.8版本,因为其查询语言InfluxQL更广为人知,且与JMeter的
Backend Listener
兼容性经过长期验证。InfluxDB 2.x虽然功能更强大,但配置上略有不同。
1. 下载与安装(以Linux为例)
# 导入InfluxData仓库密钥
wget -q https://repos.influxdata.com/influxdata-archive.key
sudo gpg --import influxdata-archive.key
# 添加仓库(这里以Debian/Ubuntu为例,其他系统请参考官网)
echo "deb https://repos.influxdata.com/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
# 安装InfluxDB 1.8
sudo apt-get update
sudo apt-get install influxdb=1.8.10-1
对于Windows或macOS用户,可以直接从InfluxData官网下载对应系统的1.8版本安装包进行安装。
2. 启动与基本配置 安装后,启动InfluxDB服务:
sudo systemctl start influxdb
sudo systemctl enable influxdb # 设置开机自启
默认情况下,InfluxDB会在
8086
端口提供HTTP API服务(用于写入和查询数据),并在
8088
端口提供RPC服务(用于备份等)。配置文件通常位于
/etc/influxdb/influxdb.conf
。
我们需要创建一个数据库来存储JMeter的数据:
# 进入InfluxDB命令行
influx
# 创建名为`jmeter`的数据库
CREATE DATABASE jmeter
# 查看数据库列表,确认创建成功
SHOW DATABASES
退出命令行(输入
exit
)。至此,InfluxDB已准备就绪。
实操心得 :在虚拟机或云服务器上部署时,确保防火墙或安全组开放了
8086端口,以便JMeter和Grafana能够访问。生产环境务必考虑设置认证,但为了初次搭建简单,我们先使用无认证模式。
3.2 Grafana 安装与启动
Grafana的安装同样简单,我们安装其开源版本。
1. 下载与安装(以Linux为例)
# 安装依赖
sudo apt-get install -y adduser libfontconfig1
# 下载并安装Grafana(此处以amd64架构为例,请根据实际情况调整)
wget https://dl.grafana.com/oss/release/grafana_10.4.2_amd64.deb
sudo dpkg -i grafana_10.4.2_amd64.deb
Windows和macOS用户可以从Grafana官网下载安装程序。
2. 启动与访问
sudo systemctl start grafana-server
sudo systemctl enable grafana-server
Grafana默认运行在
3000
端口。打开浏览器,访问
http://你的服务器IP:3000
。首次登录使用默认账号
admin
和密码
admin
,登录后会强制要求修改密码。
3.3 JMeter 与 Backend Listener 配置
确保你已安装JDK(1.8或以上)和JMeter(建议5.0以上)。JMeter的安装就是解压一个压缩包,这里不再赘述。
关键配置在于
Backend Listener
:
-
在JMeter GUI中,右键点击你的
测试计划->添加->监听器->Backend Listener。 -
在
Backend Listener implementation下拉框中,选择org.apache.jmeter.visualizers.backend.influxdb.InfluxDBBackendListenerClient。 - 配置其参数,这是核心步骤:
| 参数名 | 值 | 说明 |
|---|---|---|
| influxdbMetricsSender |
org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender
| 指定发送器为HTTP方式。 |
| influxdbUrl |
http://你的InfluxDB_IP:8086/write?db=jmeter
|
InfluxDB的写入API地址,
db=jmeter
指定我们之前创建的数据库。
|
| application |
MyPerformanceTest
| 自定义应用名,会作为Tag存入InfluxDB,用于区分不同项目或系统。 |
| measurement |
jmeter
| InfluxDB中的表(Measurement)名,默认即可。 |
| summaryOnly |
false
|
务必设为
false
。如果为
true
,则只发送聚合数据(如每分钟的均值),丢失了实时性。
|
| samplersRegex |
.*
|
匹配哪些采样器的数据被发送,
.*
表示所有。你可以用`Login
|
| testTitle |
StressTest_20240501
| 测试标题,作为Tag,方便区分多次测试。 |
| percentiles |
90;95;99
| 指定需要计算并发送的百分位数(如P90, P95, P99)。 |
4. 调整JMeter属性(可选但推荐)
为了更精细地控制数据发送,可以修改JMeter的
bin/jmeter.properties
文件:
# 设置Backend Listener的队列大小,如果压测数据量极大,可以适当调大防止丢数
backend_influxdb.queue.size=5000
# 设置批量发送的间隔时间(毫秒)和大小
backend_influxdb.batch.size=1000
backend_influxdb.flush.interval=1000
修改后需要重启JMeter GUI。
注意事项 :在非GUI模式下运行JMeter压测时(
jmeter -n -t test.jmx -l result.jtl),Backend Listener依然会正常工作并向InfluxDB发送数据。这是将监控与压测执行解耦的关键。
4. Grafana仪表盘配置与核心图表实现
4.1 添加InfluxDB数据源
登录Grafana后,点击左侧齿轮图标 ->
Data Sources
->
Add data source
。
-
选择
InfluxDB。 -
HTTP
部分:
-
URL:
http://localhost:8086(如果Grafana和InfluxDB不在同一机器,填写InfluxDB的实际地址)。 -
Access:
Server (Default)。
-
URL:
-
InfluxDB Details
部分:
-
Database:
jmeter(我们之前创建的数据库名)。 - User/Password: 如果InfluxDB未开启认证,留空即可。
-
HTTP Method:
GET。
-
Database:
-
点击
Save & Test,如果显示“Data source is working”,则表示连接成功。
4.2 创建Dashboard与第一个图表:总请求数与吞吐量(TPS)
点击左侧“田”字图标 ->
Dashboards
->
New dashboard
->
Add visualization
。
-
选择我们刚配置的
InfluxDB数据源。 -
在查询编辑器(Query)中,我们使用InfluxQL语言。首先创建一个展示
总请求数
的图表:
SELECT count("responseTime") FROM "jmeter" WHERE $timeFilter GROUP BY time($__interval) fill(null)-
count("responseTime"):计算响应时间的个数,即请求数。 -
FROM "jmeter":从jmeter这个measurement中查询。 -
WHERE $timeFilter:Grafana自动替换为当前仪表盘时间范围。 -
GROUP BY time($__interval):按时间自动分组聚合,$__interval是Grafana根据时间范围计算的合理间隔。 -
fill(null):当某个时间区间没有数据时,显示为null(断开连线)。
-
-
在右侧面板设置中:
-
Visualization选择Time series(时序图)。 -
Panel title修改为 “总请求数”。 -
在
Standard options->Unit中选择none。
-
-
接着,我们在同一个图表中添加
吞吐量(TPS)
。点击查询编辑器下方的
+ Query按钮,添加第二个查询:SELECT derivative(count("responseTime"), 1s) FROM "jmeter" WHERE $timeFilter GROUP BY time($__interval) fill(null)-
derivative(count("responseTime"), 1s):计算请求数相对于时间的变化率(导数),单位是1秒,这就得到了每秒请求数,即TPS。
-
-
为第二条查询线设置一个不同的颜色,并在
Legend中设置格式,例如{{ "{{" }}field{{ "}}" }}会显示字段名。可以将整个图表的标题改为“请求数与TPS趋势”。
4.3 实现响应时间监控(平均响应时间与百分位数)
新建一个面板,选择
Time series
。
-
查询平均响应时间:
SELECT mean("responseTime") FROM "jmeter" WHERE $timeFilter GROUP BY time($__interval) fill(null) -
添加P90、P95、P99响应时间。由于JMeter的Backend Listener会将百分位数作为独立的field写入,我们可以直接查询。添加第二个查询:
同理,可以再添加查询SELECT mean("pct90.0") AS “P90” FROM "jmeter" WHERE $timeFilter GROUP BY time($__interval) fill(null)mean("pct95.0")和mean("pct99.0")。 -
在右侧
Standard options->Unit中选择milliseconds (ms)。这个图表能清晰反映出系统响应时间的整体表现和长尾情况。
4.4 实现事务级监控与错误率统计
事务级监控
利用了InfluxDB的Tag特性。假设你的JMeter测试计划中,对不同API的采样器设置了不同的
transactionName
(可以通过
SampleResult.setSampleLabel()
或在监听器中配置获取),并作为Tag发送。
-
新建一个面板,选择
Time series。 -
在查询中使用
GROUP BY标签:
这样,图表会自动为每个不同的SELECT mean("responseTime") FROM "jmeter" WHERE $timeFilter GROUP BY time($__interval), "transaction" fill(null)transaction标签值(如“Login”, “GetProductInfo”)生成一条曲线。 -
在右侧
Legend设置中,使用{{ "{{" }}transaction{{ "}}" }}来让图例显示事务名称。
错误率统计 :
-
新建一个
Stat(统计)类型面板,它适合展示单个数值。 -
编写查询计算错误率:
SELECT (count("errorCount") / count("responseTime")) * 100 FROM "jmeter" WHERE $timeFilter-
errorCount是JMeter发送的错误计数字段(成功为0,失败为1)。 - 这个查询计算了错误请求数占总请求数的百分比。
-
-
在右侧
Standard options->Unit中选择percent (0-100)。 - 可以设置阈值(Thresholds),例如当错误率超过1%时显示为红色,超过0.5%时显示为黄色,给与视觉警报。
4.5 构建综合仪表盘与优化
将上面创建的面板拖拽排列,形成一个布局合理的仪表盘。你还可以添加:
-
当前活跃线程数
:
SELECT max("activeThreads") FROM "jmeter" WHERE $timeFilter。 -
状态码分布
:使用
Bar gauge或Pie chart面板,查询SELECT count("responseTime") FROM "jmeter" WHERE $timeFilter GROUP BY "statusCode"。 -
网络吞吐量
:如果JMeter配置了发送
sentBytes和receivedBytes,可以计算网络IO。
仪表盘优化技巧 :
-
变量与模板
:在Dashboard设置中,可以添加
Application、Transaction等变量(基于InfluxDB的Tag值),实现动态过滤,用一个仪表盘查看不同应用或事务的数据。 -
刷新与时间范围
:设置自动刷新间隔(如5s),并固定一个常用的时间范围(如
Last 30 minutes)。 - 面板链接 :可以将错误率面板链接到另一个展示详细错误日志的仪表盘。
- 告警(进阶) :虽然本次不深入,但Grafana支持基于面板查询设置告警规则,当错误率或响应时间超过阈值时,可以通过邮件、钉钉、Webhook等方式通知。
5. 平台调优、问题排查与进阶实践
5.1 性能与稳定性调优
当压测规模变大时,平台本身可能成为瓶颈。以下是一些调优方向:
InfluxDB调优 :
-
调整存储策略
:InfluxDB默认的
autogen存储策略是永久保存。对于压测数据,可以创建新的策略,例如只保留7天数据。在InfluxDB命令行执行:CREATE RETENTION POLICY "one_week" ON "jmeter" DURATION 7d REPLICATION 1 DEFAULT -
监控InfluxDB自身
:使用
SHOW STATS和SHOW DIAGNOSTICS命令,或利用Grafana监控InfluxDB的写入点数、内存使用情况,防止因写入过快导致OOM。 -
批量写入
:确保JMeter的
backend_influxdb.batch.size和flush.interval已设置,避免每个请求都发送一次HTTP调用。
JMeter调优 :
-
控制采样率
:在
Backend Listener中,可以通过samplersRegex只发送关键业务采样器的数据,减少数据量。 -
使用非GUI模式
:生产压测务必使用
-n参数在非GUI模式下运行,节省大量资源。 -
分布式压测
:当单台压力机不够时,使用JMeter Master-Slave模式。每台Slave机器上的JMeter都需要正确配置
Backend Listener指向中央的InfluxDB。
Grafana调优 :
-
查询优化
:避免在Grafana中使用过于宽泛的时间范围或过小的分组间隔(
$__interval),这会导致InfluxDB查询大量数据,拖慢渲染速度。合理利用Dashboard的时间范围选择器。 - 面板数量 :一个仪表盘内面板不宜过多,过于复杂的查询和渲染会影响浏览器性能。
5.2 常见问题与排查实录
问题1:Grafana图表中无数据
-
检查步骤
:
-
确认InfluxDB有数据
:在InfluxDB命令行执行
USE jmeter; SELECT * FROM jmeter LIMIT 10,看是否有记录。 -
检查JMeter Backend Listener配置
:确认
influxdbUrl的IP、端口、数据库名无误。查看JMeter运行日志(jmeter.log),搜索“InfluxDB”或“Error”,看是否有发送失败的错误信息。一个常见错误是网络不通或防火墙拦截。 - 检查Grafana数据源 :在Grafana的数据源配置页面,点击“Save & Test”,确认连接成功。检查查询语句的Measurement名称和字段名是否拼写正确。
-
确认InfluxDB有数据
:在InfluxDB命令行执行
问题2:数据点稀疏,图表断断续续
-
原因与解决
:这通常是因为压测请求量太小,在
$__interval时间间隔内没有数据点。可以:-
在Grafana查询中尝试去掉
GROUP BY time($__interval),直接看原始数据点(SELECT "responseTime" FROM "jmeter" WHERE $timeFilter)。 -
或者,在Dashboard设置中增大时间范围,Grafana会自动增大
$__interval。 -
检查JMeter的
summaryOnly是否误设为true,这会导致只发送分钟级聚合数据。
-
在Grafana查询中尝试去掉
问题3:InfluxDB写入失败,报“field type conflict”
-
原因
:InfluxDB中,同一个Field(字段)在同一个Shard内,其数据类型必须一致(如全部是整数或全部是浮点数)。如果JMeter先写入了一个整型的
responseTime(如150),后又写入了一个带小数的responseTime(如150.5),就会冲突。 -
解决
:确保JMeter发送的数据类型一致。可以在JMeter中使用
JSR223 PostProcessor等组件,对responseTime进行强制类型转换(如Float.parseFloat()),或者确保响应时间总是以浮点数形式计算。最根本的预防措施是: 对于每次新的压测,使用一个新的testTitle或application值,这样数据会写入不同的Series,避免与历史数据冲突。
问题4:高并发压测下,监控数据延迟严重
-
排查
:
- 监控InfluxDB所在机器的CPU、内存、磁盘IO。磁盘IO瓶颈(特别是如果使用机械硬盘)是常见原因。考虑使用SSD。
-
检查JMeter压力机的资源是否耗尽,导致
Backend Listener发送线程被阻塞。 -
增大InfluxDB的
[http]配置中的max-connection-limit和max-concurrent-write-limit。 -
考虑使用InfluxDB的
UDP写入
方式(需配置
influxdbMetricsSender为对应的UDP发送器),UDP是无连接的,吞吐量更高,但需注意可能丢包,适合对少量数据丢失不敏感的场景。
5.3 进阶实践:与CI/CD流水线集成
这套监控平台的价值在CI/CD流水线中能得到更大发挥。思路是:
-
参数化
:将JMeter测试脚本、InfluxDB的
application、testTitle等标签设计为可由构建工具(如Jenkins)传递的参数。 -
自动化执行
:在流水线中,使用Jenkins的
Performance Plugin或直接执行Shell命令启动JMeter压测。 -
动态仪表盘
:Grafana Dashboard可以使用包含构建编号(
$BUILD_NUMBER)等变量的链接。在压测开始时,脚本生成一个包含了本次测试所有关键参数(应用名、事务名、构建ID、时间范围)的Grafana URL。 - 结果判定 :在压测结束后,可以通过Grafana API或直接从InfluxDB查询关键指标(如平均响应时间是否小于200ms,错误率是否小于0.1%),并以此作为流水线通过或失败的依据之一。
例如,一个简单的Shell脚本片段可以这样生成Dashboard链接:
GRAFANA_DASHBOARD_URL="http://grafana-server:3000/d/your-dashboard-uid?orgId=1&from=${start_time_millis}&to=${end_time_millis}&var-application=${APPLICATION_NAME}&var-build=${BUILD_NUMBER}"
echo "性能监控仪表盘: ${GRAFANA_DASHBOARD_URL}"
将这个链接输出到构建日志或发送到团队群聊,所有人就能立即查看本次构建的性能表现。
搭建并熟练使用这套可视化监控平台,彻底改变了我们团队进行性能测试的方式。它让性能测试从一份“事后报告”变成了一个“实时过程”,让性能问题在发生的那一刻就被暴露和关注。最大的体会是,工具链的打通带来的效率提升是巨大的,它促使测试、开发和运维围绕同一组真实、直观的数据进行对话和协作。如果你还在为如何向团队展示压测实时状态而烦恼,强烈建议你花一个下午的时间,跟着上述步骤亲手搭建一遍。



6962

被折叠的 条评论
为什么被折叠?



