搭建jmeter+influxdb+grafana压测实时监控平台(超详细,小白适用)
1.前言
在使用jmeter做性能测试的时候,监控系统性能的时候,无论是使用插件还是报告生成,都没法实现实时监控。使用JMeter+Influxdb+Grafana可以实现实时监控。
本次环境搭建各软件版本说明:
Grafana v6.2.5
InfluxDB 1.7.0
JMeter 5.2.1
2.Influxdb简介
InfluxDB是用Go语言编写的高性能、高可用的分布式时序数据存储数据库,无其他依赖,安装简单快速。
该数据库现在主要用于存储涉及大量的时间戳数据,如DevOps监控数据,APP metrics, loT传感器数据和实时分析数据。
InfluxDB特征:
- 无结构(无模式):可以是任意数量的列
- 可以设置metric的保存时间
- 支持与时间有关的相关函数(如min、max、sum、count、mean、median等),方便统计
- 支持存储策略:可以用于数据的删改。(influxDB没有提供数据的删除与修改方法)
- 支持连续查询:是数据库中自动定时启动的一组语句,和存储策略搭配可以降低InfluxDB的系统占用量。
- 原生的HTTP支持,内置HTTP API
- 支持类似sql语法select * from mysql.user
- 支持设置数据在集群中的副本数
- 支持定期采样数据,写入另外的measurement,方便分粒度存储数据。
schemaless: 结构型数据库类似Mysql需要先定义列,influxdb无需预先定义,无结构的
与传统数据库中的名词比较
influxDB中的名词 | 传统数据库的概念 |
database | 数据库 |
measurement | 数据库中的表 |
points | 表里面的一行数据 |
influxdb的points数据说明
- time:默认存储数据会有时间,时间无需关心,会帮我们自动插入
- tags:用来存储数据标识,比如CPU.idle
- fileds:用来存储数据 value=90
3.下载
定位到/usr/local目录下,执行命令:wget https://dl.influxdata.com/influxdb/releases/influxdb-1.7.0.x86_64.rpm --no-check-certificate,然后等待下载完成
4.解压安装
执行命令:rpm -ivh influxdb-1.7.0.x86_64.rpm
安装完之后,生成默认的配置文件 /etc/influxdb/influxdb.conf,可以到/ect目录下去查看
5.修改influxDB配置文件
执行命令:vi /etc/influxdb/influxdb.conf,将最终修改的配置如下:
[[graphite]]
# Determines whether the graphite endpoint is enabled.
enabled = true
database = "jmeter" # 数据库名称
retention-policy = ""
bind-address = ":2003" # 端口
protocol = "tcp"
consistency-level = "one"
修改以下信息
[meta]
dir = "/usr/local/influxdb/meta" #存放最终存储的数据,文件以.tsm结尾
[data]
dir = "/usr/local/influxdb/data" #存放数据库元数据 wal
wal-dir = "/usr/local/influxdb/wal" #存放预写日志文件
修改HTTP端口信息
[http]
# Determines whether HTTP endpoint is enabled.
enabled = true
# The bind address used by the HTTP service.
bind-address = ":8086"
修改完成后执行:wq保存退出
6.在上一步中我们设置了存放数据的目录为/usr/local/influxdb,这个目录不会自动生成,因此需要手动创建并授权,执行命令如下:
我这里使用的是root用户,使用其他用户如果报权限不足则需要切换到root用户
7.启动influxDB服务
启动influxDB服务有两种方式:
方式一: 直接执行命令: influxd -config /etc/influxdb/influxdb.conf
启动后显示如下图:
方式二(推荐):
-bash-4.2# vi /etc/profile
添加变量:export INFLUXDB_CONFIG_PATH=/etc/influxdb/influxdb.conf,然后保存,如下图:
执行:source /etc/profile,是配置文件生效后,执行:influxd &,启动
influxDB的tcp端口是8088,执行:netstat -antp|grep 8088,显示如下则表示端口启动成功
8.创建数据库及用户
执行命令如下:
-bash-4.2$ influx
> show databases
> CREATE DATABASE jmeter
> use jmeter
> create user "admin" with password '123456' with all privileges
此处设置的用户名和密码需要记录下来,后面配置JMeter和Grafana时有用到
注:这里要注意一下,CREATE DATABASE必须使用大写
网上有使用小写创建数据库,如:create databases "jmeter",执行后会报错,报错信息如下
ERR: error parsing query: found DATABASES, expected CONTINUOUS, DATABASE, USER, RETENTION, SUBSCRIPTION at line 1, char 8
Warning: It is possible this error is due to not setting a database.
Please set a database with the command "use <database>".
端口说明:
2003端口:Jmeter往数据库发数据的端口,服务器端也是该端口接收数据,所以如果使用云服务器ECS的话,需要开启该2003端口
8086端口,Grafana从数据库取数据的端口
9.JMeter配置
新建一个测试计划,新建一个线程组,右键测试计划选择Add->Listener->Backend Listener,如果使用的是中文则添加后端监听器的路径是:右键测试计划选择添加->监听器->后端监听器
添加后端监听器,配置如下图:
新建请求,然后执行
10.在服务器上查看influxdb是否有接收数据成功:
执行如下命令:
-bash-4.2$ influx
> show databases
> use jmeter
> show measurements
11. 安装配置grafana
下载安装:
#下载 wget https://dl.grafana.com/oss/release/grafana-6.2.5-1.x86_64.rpm #安装 sudo yum localinstall grafana-6.2.5-1.x86_64.rpm #添加到服务并自启动 /sbin/chkconfig --add grafana-server systemctl enable grafana-server.service #启动服务 service grafana-server start #查看安装 find / -name grafana
grafana默认启动3000端口,可以使用netstat -antp | grep 3000 ,确认端口是否启动,端口启动后可通过一下地址访问Grafana: 服务器IP地址:3000
会展示默认的登录界面,默认用户名密码都是admin,登录进去后如下图
配置数据库:
选择InfluxDB
最终配置如下图,配置好后点击下面的 Save & Test 按钮,提示 Data source is working 就表示数据库连接成功
接下来配置监控面板,配置panel有两种方式:1.手动配置panel 2.在官网下载panel模板
下面先讲第一种方式:
点击左上角Grafana图标,进入Home界面,点击左侧“+”号菜单,点击Dashboard,
进入New dashboard界面,点击Add Query(各个版本的显示不一样,但是操作流程是一样的)
进入面板设置界面,如下图
说明:想了解这些查询具体是什么意思,可以访问Jmeter的官网地址去查看 http://jmeter.apache.org/usermanual/realtime-results.html
线程数/用户相关指标 test.minAT-Min active threads:最小活跃线程数 test.maxAT-Max active threads:最大活跃线程数 test.meanAT-Mean active threads:活跃线程数 test.startedT-Started threads:启动线程数 test.endedT-Finished threads:结束线程数 响应时间指标 .ok.count:采样器的成功响应数 .h.count:每秒点击数 .ok.min:采样器成功最短响应时间 .ok.max:采样器成功最长响应时间 .ok.avg:采样器成功平均响应时间 .ok.pct:采样器成功响应百分比 .ko.count:采样器失败响应数 .ko.min:采样器失败的响应最短时间 .ko.max:采样称失败最长响应时间 .ko.avg:采样器失败平均响应时间 .ko.pct:采样器失败响应百分比 .a.count:采样器响应数(ok.count和ko.count的总和) .a.min:采样器最小响应时间(ok.count和ko.count的最小值) .a.max:采样器最大响应时间(ok.count和ko.count的最大值) .a.avg:采样器平均响应时间(ok.count和ko.count的平均值) .a.pct:采样器响应百分比(根据和失败样本的总数计算) Backend Listener的默认百分位设置为“90;95;99”,即百分位数为90%,95%和99%。 Graphite使用点(“.”)去拆分的元素,这可能与十进制百分位值混淆。JMeter转换任何此类值,用下划线(“ - ”)替换点(“.”)。例如,“99.9 ”变为“99_9 ” 默认情况下,JMeter发送在samplerName“all”下累计的所有采样器的指标。 如果配置了 BackendListenerSamplersList,那么JMeter还会发送匹配样本名称的指标,前提是配置 summaryOnly=true
最终显示结果如下:
接下来讲第二种方式:模板方式
点击左上角Grafana图标,点击Home,然后点击Find dashboards on Grafana.com,会跳转到Grafana官网,或者可以直接进入官网:https://grafana.com/grafana/dashboards?utm_source=grafana_search
左侧输入查询模板的条件,如下图,这里选择比较常用的JMeter Load Test模板
下载JMeter-InfluxDB-Writer界面如下图,这里下载的是最新版本1.2版本,点击JMeter-InfluxDB-Writer-plugin-1.2.jar即可下载
下载完成后上传到JMeter安装目录lib/ext目录下,如下图:
然后重启jmeter,选择rocks.nt.apm.jmeter.JMeterinfluxDBBackendListenerClient,输入influxDB的host和端口,之前创建Influxdb的用户名和密码,然后保存。如果host默认是localhost,直接执行会报错:Failed to connect to localhost/0:0:0:0:0:0:0:1:8086
上图中的用户名和密码可以在服务器中查看,密码是之前创建用户的时候自己输入的,执行命令:
influx
show users
接下来导入Grafana模板,点击左上角Grafana Logo,点击Home,然后选择Import dashboard
打开的界面如下图,这些需要填写模板ID,模板ID获取详见下一步
在JMeter Load Test模板界面点击Copy ID to Clipboard,将ID复制好然后粘贴到Grafana导入模板界面,如下图:
输入模板ID 1152后,点击空白处,会显示如下图信息,请按照下图中进行修改:
查看模板可以点击左上角Grafana Logo,点击模板名称,这里是默认的JMeter Load Test
默认模板显示如下图:
重启JMeter,执行测试,在Grafana界面的右上角选择要显示的时间,最终显示压测结果如下图(右上角刷新时间建议选小一点,效果会比较明显):
遇到的问题:
1.创建influxdb数据库的时候使用create databases "jmeter",报错
解决办法:必须使用大写来进行创建,命令是:CREATE DATABASE jmeter
2.执行Jmeter请求,jmeter日志报Error writing to Graphite: connect timed out,具体报错信息如下:
2020-07-17 16:51:29,810 ERROR o.a.j.v.b.g.TextGraphiteMetricsSender: Error writing to Graphite: connect timed out
java.net.SocketTimeoutException: connect timed out
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[?:1.8.0_171]
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) ~[?:1.8.0_171]
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[?:1.8.0_171]
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[?:1.8.0_171]
at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_171]
at java.net.PlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_171]
at java.net.SocksSocketImpl.connect(Unknown Source) ~[?:1.8.0_171]
at java.net.Socket.connect(Unknown Source) ~[?:1.8.0_171]
at org.apache.jmeter.visualizers.backend.graphite.SocketOutputStreamPoolFactory.create(SocketOutputStreamPoolFactory.java:77) ~[ApacheJMeter_components.jar:5.2.1]
at org.apache.jmeter.visualizers.backend.graphite.SocketOutputStreamPoolFactory.makeObject(SocketOutputStreamPoolFactory.java:48) ~[ApacheJMeter_components.jar:5.2.1]
at org.apache.jmeter.visualizers.backend.graphite.SocketOutputStreamPoolFactory.makeObject(SocketOutputStreamPoolFactory.java:34) ~[ApacheJMeter_components.jar:5.2.1]
at org.apache.commons.pool2.impl.GenericKeyedObjectPool.create(GenericKeyedObjectPool.java:1041) ~[commons-pool2-2.7.0.jar:2.7.0]
at org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:342) ~[commons-pool2-2.7.0.jar:2.7.0]
at org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:265) ~[commons-pool2-2.7.0.jar:2.7.0]
at org.apache.jmeter.visualizers.backend.graphite.TextGraphiteMetricsSender.writeMetrics(TextGraphiteMetricsSender.java:110) [ApacheJMeter_components.jar:5.2.1]
at org.apache.jmeter.visualizers.backend.graphite.TextGraphiteMetricsSender.writeAndSendMetrics(TextGraphiteMetricsSender.java:104) [ApacheJMeter_components.jar:5.2.1]
at org.apache.jmeter.visualizers.backend.graphite.GraphiteBackendListenerClient.sendMetrics(GraphiteBackendListenerClient.java:183) [ApacheJMeter_components.jar:5.2.1]
at org.apache.jmeter.visualizers.backend.graphite.GraphiteBackendListenerClient.run(GraphiteBackendListenerClient.java:146) [ApacheJMeter_components.jar:5.2.1]
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_171]
at java.util.concurrent.FutureTask.runAndReset(Unknown Source) [?:1.8.0_171]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source) [?:1.8.0_171]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) [?:1.8.0_171]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_171]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_171]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_171]
打开配置文件,发现enabled的值为false,需要改为true,设置结果如下图:
修改之后还是没有解决,因为用的是阿里云服务器,需要去阿里云开启对应的端口,设置端口如下图,我这里是外网访问,端口一定开放公网入方向才可以,可以是内网则需要在内网入方向下开放2003端口
然后重新执行JMeter,执行一段时间后在服务器上查看influxdb的数据库,显示结果如下图则表示jmeter发送数据到influxdb成功
3.Jmeter执行后查看influxdb数据库,执行show measurements时显示无数据
原因分析:服务器没有打开防火墙
解决方法:
firewall-cmd --state #查看防火墙状态,如果是running则表示防火墙已开启,使用 sys
systemctl stop firewall.service #关闭防火墙 或者使用systemctl stop firewalld.service
systemctl start firewall.service #开启防火墙 或者使用systemctl start firewalld.service
关闭防火墙后,在Jmeter上执行请求,然后在服务器上进入influx查看是否数据,结果如下图则表示jmeter的数据已经推送到influxdb
排查过程:1.服务器本地查看端口8086和2003是否开启成功,结果显示两个端口是开启成功且本地可以访问的
2.Win10上ping 服务器,可以ping通,但是端口ping不通
3.查看防火墙
参考资料:
https://www.cnblogs.com/mike-liu/p/10080351.html