一、引言

压测过程中,我们需要监控服务器、数据库的各项性能指标。
使用 JMeter 进行压测,压测结束后,可以通过 HTML 报告可以查阅压测结果。但是这种方式存在比较致命的缺点:只能在压测流程结束后,才能查看指标数据。无法观测执行过程中的异常波动,不具备实时性。
可以在 JMeter 脚本中增加 Basic Graphs 等插件,通过树 + 图 + 表等方式查看压测过程中指标,但是这种方式通常在调试脚本的时候使用,正式压测时不推荐。因为 JMeter 使用 Java 实现,并不擅长图形绘制,这样的组件在压测过程中执行极其耗损性能,影响压测执行及压测结果的准确性。
因此,需要搭建监控系统,实时的监控整个压测过程。

二、监控系统组成

1.InfluxDB
InfluxDB 是一款用 Go 语言编写的开源分布式时序、事件和指标数据库,无需外部依赖。该数据库现在主要用于存储涉及大量的时间戳数据,如 DevOps 监控数据,APP metrics, loT 传感器数据和实时分析数据。
2.Prometheus
Prometheus 是一个开源的系统监控和警报工具包,在 Prometheus + Grafana 的体系架构下,Prometheus 相当于一个注册中心。
3.Grafana
一个开源软件,拥有丰富的指标仪表盘和图形编辑器,适用 Graphite, Elasticsearch, OpenTSDB, Prometheus,InfluxDB。简单点说就是一套开源 WEB 可视化平台。

三、监控系统实现原理

JMeter 引入 Backend Listener 将在压测过程中实时采集并发送统计指标数据发送到 Influxdb 数据库,Grafana 数据源连接到 Influxdb,并实时读取 InfluxDB 数据库中的数据,通过配置的可视化看板展示测试指标数据。
● 采集 -- 通过 JMeter 中配置 Backend Listener 去实时采集数据
● 存储 -- 在 Prometheus/InfluxDB 中进行相关配置,存储采集来的数据
● 展示 -- 在 Grafana 中进行相关配置,读取 InfluxDB 数据库中的数据,配置相应的 dashboard 进行展示 JMeter 采集到的数据

四、监控系统搭建方式

支持在不同的运行环境搭建监控系统:
● windows 环境搭建 JMeter + Influxdb/prometheus + Grafana 监控系统
● 基于 docker-compose 搭建 JMeter + Influxdb/prometheus + Grafana 监控系统
windows 上搭建监控系统,比较简单,适合小流量压测执行。
使用场景更高的是对服务端的监控。因此这个分章节,主要介绍 Linux 环境下监控系统的搭建。

那么监控系统为什么使用 Docke-compose 搭建呢?原因如下:
● 简化管理:虽然不像微服务架构动辄几十服务,监控系统涉及服务要是单独管理还是比较麻烦的,手动启停维护工作量较大。
● 解决服务依赖性问题:监控系统服务存在依赖关系,需要相互配合才能实现监控系统的功能。
● 可移植性:只需要编写一份 docker-compse.yml,及提供相应服务的配置文件,可以快速移植到任何需要监控的服务器中。

五、基于 docker-compose 搭建监控系统的具体实现

  1. docker-compse.yml 编写 主要配置项说明: ①.JMeter 为了解耦,没有在监控系统中配置 JMeter 相关内容,只配置监控系统最小化安装。 JMeter 分布式压测使用预制的 docker Master/Slave image,灵活控制 slave 的个数和主从的端口号。 ②.Grafana / prometheus 从 Grafana 和 prometheus 官网拿到 docker-compose.yml,作为配置文件 docker-compose.yml 的节点内容,因此版本号是 latest。 当然也可以使用 Grafana / prometheus 自有 docker image 的版本号,不过尽量不要使用过低版本号,避免版本兼容问题。
官网链接如下:
● Grafana:https://grafana.com/docs/grafana/latest/installation/docker/
● prometheus:https://prometheus.io/docs/guides/cadvisor/#prometheus-configuration

③.Influxdb / Prometheus
存储节点,都配置了 docker 数据卷,用于监控数据的持久化存储。
当我们每次对服务做升级时,或者做了性能优化时,都可以再次进行压测,对比历史压测数据,查看优化的效果。

version: '3'

services:
    grafana:
        image: grafana/grafana:latest
        container_name: jk_grafana
        hostname: grafana
        restart: always
        ports:
            - 3000:3000
        env_file:
            - ./grafana/config.monitoring
    prometheus:
        image: prom/prometheus:latest
        container_name: jk_prometheus
        hostname: prometheus
        restart: always
        volumes:
            - ./prometheus:/etc/prometheus
            - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
        command:
            - --config.file=/etc/prometheus/prometheus.yml
        ports:
            - 9090:9090


    influxdb:
        image: influxdb:1.8.10
        container_name: jk_influxdb
        hostname: influxdb
        restart: always
        volumes:
            - ./influxdb/db:/var/lib/influxdb
            - ./influxdb/config/influxdb.generated.conf:/etc/influxdb/influxdb.generated.conf
        ports:
            - 8083:8083
            - 8086:8086
            - 8090:8090

2.文件目录结构
准备好监控系统的 docker-compse.yml 后,各个服务还有单独的配置文件。系统的目录结构如下:

.
├── docker-compose.yml
├── grafana
│   ├── config.monitoring
│   └── dashboard
│       ├── alerting.json
│       ├── ping_dashboard.json
│       └── variable.json
├── prometheus
│   └── prometheus.yml

3.配置文件

各个服务还有单独的配置文件,具体如下:
①. Grafana

grafana:
        env_file:
            - ./grafana/config.monitoring
vim config.monitoring

GF_SECURITY_ADMIN_PASSWORD=admin
GF_USERS_ALLOW_SIGN_UP=false

②. prometheus

prometheus:
        command:
            - --config.file=/etc/prometheus/prometheus.yml
vim prometheus.yml

global:
  scrape_interval: 10s
  evaluation_interval: 15s

4.启动容器
进入 docker-compose.yml 目录下,执行命令启动容器

[root@localhost jkxt]# pwd
/root/handan3/jkxt
[root@localhost jkxt]# docker-compose up -d

Creating jk_redis ... done
Creating jk_cadvisor ... done
Creating jk_prometheus ... done
Creating jk_influxdb ... done


[root@localhost jkxt]# docker ps
CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS         PORTS                                                                                                                             NAMES
280c447c1e97   prom/prometheus:latest   "/bin/prometheus --c…"   2 minutes ago   Up 2 minutes   0.0.0.0:9090->9090/tcp, :::9090->9090/tcp                                                                                         jk_prometheus
a00db4de47da   google/cadvisor:latest   "/usr/bin/cadvisor -…"   2 minutes ago   Up 2 minutes   8080/tcp, 0.0.0.0:8081->8081/tcp, :::8081->8081/tcp                                                                               jk_cadvisor
5c04c5ebc022   redis:latest             "docker-entrypoint.s…"   2 minutes ago   Up 2 minutes   0.0.0.0:6380->6379/tcp, :::6380->6379/tcp                                                                                         jk_redis
9edb14c81e3c   grafana/grafana:latest   "/run.sh"                2 minutes ago   Up 2 minutes   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp                                                                                         jk_grafana
c582e8e25dee   influxdb:1.8.10          "/entrypoint.sh infl…"   2 minutes ago   Up 2 minutes   0.0.0.0:8083->8083/tcp, :::8083->8083/tcp, 0.0.0.0:8086->8086/tcp, :::8086->8086/tcp, 0.0.0.0:8090->8090/tcp, :::8090->8090/tcp   jk_influxdb

备注:如果有 running 状态的服务,需要先 docker-compose down 正在运行服务, 不然 docker-compose up 时会报错端口已被占用。

5.配置监控系统

5.1 JMeter 添加 Backend Listener
①.JMeter 先安装插件 jmeter-prometheus-plugin-0.6.0.jar

②.配置 Backend Listener
Linux 上要配置上具体的服务器 ip【http://10.19.1.136:8086/write?db=jmeterDB

5.2 JMeter 关联 Influxdb
由于 JMeter 需要将数据写入 Influxdb 中,需要先创建好数据库,如下步骤:

①.进入 Influxdb 容器中

[root@localhost jkxt]# docker-compose exec influxdb bash

②.输入 influxdb 进入 influxdb 命令行模式

root@influxdb:/# influx
Connected to http://localhost:8086 version 1.8.10
InfluxDB shell version: 1.8.10
> show databases;
name: databases
name
----
_internal
> create database jmeterDB

③.创建一个数据库命名为:jmeterDB(一定要同 JMeter Backend Listener 中配置的一致)

> create database jmeterDB
> show databases
name: databases
name
----
_internal
jmeterDB
> 

④.启动并进入 master 容器

docker exec -it jmeter-cljyc-master-1 /bin/bash

⑤.执行压测脚本

jmeter \
-n -t ./jmx/cljzyyconeLinux.jmx \
-l ./jtl/cljyc.jtl \
-e -o ./report \
-j /log/jmeter-master.log \
-Dserver.rmi.ssl.disable=true \
-Dclient.rmi.localport=60000\
-Djava.rmi.server.hostname=10.19.1.136 \
-Dserver_port=1099 \
-Dserver.rmi.ssl.disable=true \
-JthreadNum=10 -JrampTime=10 -JstepTime=10 -Jduration=10 

⑥.Influxdb 中查看是否数据存入

>show databases
>use jmeterDB
>show measurements
>select * from jmeter limit 5

到这,说明 JMeter 和 Iinfluxdb 已关联成功。

5.3 Influxdb/Prometheus 关联 Grafana
这部分在网上可以找到相关资料,比较简单,就不做详细描述。
以 Influxdb 关联 Grafana 为例,简要描述过程如下:
①.打开浏览器
● Linux 服务器输入 ip:3000,如:http://10.19.1.136:3000/?orgId=1
②.点击入口添加数据库,数据源选择 InfluxDB
③.设置 连接的数据库:jmeterDB,以及 Grafana 的账号和密码。
④.到 Grafana 官网,选择合适的 DashBoard。
⑤.在 Grafana 中 import 指定 DashBoard。

6.运行监控脚本查看效果

在 JMeter 中执行脚本,查看效果

到这里,JMeter 的 Summary Report 的数据就可以在 Grafana Dashboard 上展示出来

六、总结

在上一篇文章 -- 性能测试概览中,概要描述了压测整个过程,使用的环境和工具。
本章节重点在监控环境搭建上,没有监控系统的压测就如蒙眼狂奔,不仅无法有效实现监控目标,更可能在压测执行过程带来未知的风险。
下一章节,将讲解 JMeter 压测环境的搭建。


↙↙↙阅读原文可查看相关链接,并与作者交流