最强性能监控工具之Grafana+Prometheus+Exporters

joytrian
发布于 2023-6-1 11:58
浏览
0收藏

最强性能监控工具之Grafana+Prometheus+Exporters

1 监控逻辑

最流行的监控逻辑:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

有测试工具、监控工具,才能做性能分析和瓶颈定位。

不管数据啥形式展示,最要紧还是数据来源和含义,以做正确判断。

2 JMeter+InfluxDB+Grafana数据展示逻辑

JMeter压测时,使用JMeter控制台查看结果:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

或装插件看结果:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

或JMeter生成HTML:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

压力工具只关心三条曲线:TPS(T由测试目标定义)、响应时间、错误率。错误率还只是辅助排查问题的曲线,没问题时,只看TPS、响应时间。

2.1 传统方案的缺陷

  1. 整理结果费时
  2. 在GUI用插件看曲线,高并发时不现实
  3. 在场景运行时间比较长时,采用生成HTML,会出现消耗内存过大的情况。有很多生成的图也并不关注
  4. 生成的结果保存之后再查看比较麻烦,还一个个找

2.2 解决方案

用JMeter的Backend Listener实时发数据到InfluxDB或Graphite。Graphite Backend Listener支持在JMeter 2.13版本,InfluxdDB Backend Listener的支持在JMeter 3.3,都是异步发数据,以便查看。

有这JMeter发给InfluxDB的数据,无需看上面的那些HTML数据,也能直观看到系统的性能趋势。以后复看也方便比对。

3 JMeter+InfluxDB+Grafana结构

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

JMeter发送压力到服务器的同时,统计TPS、响应时间、线程数、错误率等信息。

默认每30s在控制台输出一次(jmeter.properties参数#summariser.interval=30可以控制)。

配置Backend Listener后,将统计结果异步发到InfluxDB。最后在Grafana配置:

  • InfluxDB数据源
  • JMeter显示模板

就能实时查看JMeter测试结果,这看到的数据和控制台数据一样。

4 数据的传输和展示逻辑

4.1 JMeter中Backend Listener配置

就InfluxDB的Backend Listener做个说明。在脚本中加上即可:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

先配好influxdb Url、application等信息,application配置可看成是场景名。

4.2 JMeter如何发数据给InfluxDB

关键源码:

private void addMetrics(String transaction, SamplerMetric metric) {
  // FOR ALL STATUS
  addMetric(transaction, metric.getTotal(), metric.getSentBytes(), metric.getReceivedBytes(), TAG_ALL, metric.getAllMean(), metric.getAllMinTime(),
          metric.getAllMaxTime(), allPercentiles.values(), metric::getAllPercentile);
  // FOR OK STATUS
  addMetric(transaction, metric.getSuccesses(), null, null, TAG_OK, metric.getOkMean(), metric.getOkMinTime(),
          metric.getOkMaxTime(), okPercentiles.values(), metric::getOkPercentile);
  // FOR KO STATUS
  addMetric(transaction, metric.getFailures(), null, null, TAG_KO, metric.getKoMean(), metric.getKoMinTime(),
          metric.getKoMaxTime(), koPercentiles.values(), metric::getKoPercentile);


  metric.getErrors().forEach((error, count) -> addErrorMetric(transaction, error.getResponseCode(),
              error.getResponseMessage(), count));
}

站在全局统计视角,这里把JMeter运行的统计结果:

  • 如事务的Total请求、发送接收字节、平均值、最大值、最小值等,都加到metric
  • 同时也把成功/失败的事务信息加到metric

更多的添加metric的步骤看JMeter源码​​InfluxdbBackendListenerClient.java​​。

保存metric后,再用InfluxdbMetricsSender发到Influxdb:

   @Override
    public void writeAndSendMetrics() {
 ........
        if (!copyMetrics.isEmpty()) {
            try {
                if(httpRequest == null) {
                    httpRequest = createRequest(url);
                }
                StringBuilder sb = new StringBuilder(copyMetrics.size()*35);
                for (MetricTuple metric : copyMetrics) {
                    // Add TimeStamp in nanosecond from epoch ( default in InfluxDB )
                    sb.append(metric.measurement)
                        .append(metric.tag)
                        .append(" ") //$NON-NLS-1$
                        .append(metric.field)
                        .append(" ")
                        .append(metric.timestamp+"000000") 
                        .append("\n"); //$NON-NLS-1$
                }


                StringEntity entity = new StringEntity(sb.toString(), StandardCharsets.UTF_8);
                
                httpRequest.setEntity(entity);
                lastRequest = httpClient.execute(httpRequest, new FutureCallback<HttpResponse>() {
                    @Override
                    public void completed(final HttpResponse response) {
                        int code = response.getStatusLine().getStatusCode();
                        /*
                         * HTTP response summary 2xx: If your write request received
                         * HTTP 204 No Content, it was a success! 4xx: InfluxDB
                         * could not understand the request. 5xx: The system is
                         * overloaded or significantly impaired.
                         */
                        if (MetricUtils.isSuccessCode(code)) {
                            if(log.isDebugEnabled()) {
                                log.debug("Success, number of metrics written: {}", copyMetrics.size());
                            } 
                        } else {
                            log.error("Error writing metrics to influxDB Url: {}, responseCode: {}, responseBody: {}", url, code, getBody(response));
                        }
                    }
                    @Override
                    public void failed(final Exception ex) {
                        log.error("failed to send data to influxDB server : {}", ex.getMessage());
                    }
                    @Override
                    public void cancelled() {
                        log.warn("Request to influxDB server was cancelled");
                    }
                });               
 ........
            }
        }
    }

通过writeAndSendMetrics,就将所有保存的metrix都发给InfluxDB。

5 InfluxDB存储结构

InfluxDB如何存储:

> show databases
name: databases
name
----
_internal
jmeter

> use jmeter
Using database jmeter


> show MEASUREMENTS
name: measurements
name
----
events
jmeter

> select * from events where application='7ddemo'
name: events
time                application text                title
----                ----------- ----                -----
1575255462806000000 7ddemo      Test Cycle1 started ApacheJMeter
1575256463820000000 7ddemo      Test Cycle1 ended   ApacheJMeter
..............

> select * from jmeter where application='7ddemo' limit 10
name: jmeter
time                application avg                count countError endedT hit max maxAT meanAT min minAT pct90.0            pct95.0           pct99.0 rb responseCode responseMessage sb startedT statut transaction
----                ----------- ---                ----- ---------- ------ --- --- ----- ------ --- ----- -------            -------           ------- -- ------------ --------------- -- -------- ------ -----------
1575255462821000000 7ddemo                                          0              0     0          0                                                                                     0               internal
1575255467818000000 7ddemo      232.82352941176472 17    0                 17  849              122       384.9999999999996  849               849     0                               0           all    all
1575255467824000000 7ddemo      232.82352941176472 17                          849              122       384.9999999999996  849               849     0                               0           all    0_openIndexPage
1575255467826000000 7ddemo      232.82352941176472 17                          849              122       384.9999999999996  849               849                                                 ok     0_openIndexPage
1575255467829000000 7ddemo                                          0              1     1          1                                                                                     1               internal
1575255472811000000 7ddemo      205.4418604651163  26    0                 26  849              122       252.6              271.4             849     0                               0           all    all
1575255472812000000 7ddemo                                          0              1     1          1                                                                                     1               internal
1575255472812000000 7ddemo      205.4418604651163  26                          849              122       252.6              271.4             849                                                 ok     0_openIndexPage
1575255472812000000 7ddemo      205.4418604651163  26                          849              122       252.6              271.4             849     0                               0           all    0_openIndexPage
1575255477811000000 7ddemo      198.2142857142857  27    0                 27  849              117       263.79999999999995 292.3500000000001 849     0                               0           all    all

InfluxDB中创建两个MEASUREMENTS:

  • events
  • jmeter

这两个各自存数据,在界面中配置的testtile和eventTags放在events这个MEASUREMENTS中。在模板中这两个值暂都不用。

在jmeter这个MEASUREMENTS中,可看到application和事务的统计信息,这些值和控制台一致。

在Grafana中显示时,就是从这个表中取出数据,根据时序做曲线。

6 Grafana配置

有了JMeter发送到InfluxDB中的数据后,下面得配置Grafana展示。

6.1 配置一个InfluxDB数据源

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

在这配置URL、Database、User、Password,点击保存。

6.2 添加一个JMeter dashboard

常用dashboard是Grafana官方ID为5496的模板。导入进来后,选好对应数据源:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

就看到界面啦:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

这时还没数据,稍后做个示例,看JMeter的数据怎么对应的该界面数据。

7 数据对比

图中两个重要的数据查询语句。

7.1 TPS曲线

SELECT last("count") / $send_interval
FROM "$measurement_name"
WHERE ("transaction" =~ /^$transaction$/
       AND "statut" = 'ok')
       AND $timeFilter
       GROUP BY time($__interval)

即Total TPS,在这称为throughput。

这里取的数据来自MEASUREMENTS中成功状态的所有事务。

7.2 响应时间曲线

SELECT mean("pct95.0")
FROM "$measurement_name"
WHERE ("application" =~ /^$application$/)
AND $timeFilter
GROUP BY "transaction", time($__interval) fill(null)

这是用95 pct内的响应时间画出的曲线。

7.3 整体展示效果

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

7.4 JMeter配置场景

10个线程,每个线程迭代10次及两个HTTP请求:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

会产生10x10x2=200次请求。JMeter跑下:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

请求数和预想一样,看Grafana展示结果:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

针对每个事务的统计:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

7.5 意义

JMeter到Grafana的展示过程完成。以后就:

  • 不用再保存JMeter执行结果
  • 不用等JMeter输出HTML

8 node_exporter+Prometheus+Grafana数据展示逻辑

性能测试,在常用的Grafana+Prometheus+Exporter逻辑,第一步就要看os资源。

以node_exporter为例,说明os抽取数据的逻辑,来看监控数据的来源:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

node_exporter可支持很多个os:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

当然你也能扩展自己的Exporter。

8.1 配置node_exporter

node_exporter目录:

[root@7dgroup2 node_exporter-0.18.1.linux-amd64]# ll
total 16524
-rw-r--r-- 1 3434 3434    11357 Jun  5 00:50 LICENSE
-rwxr-xr-x 1 3434 3434 16878582 Jun  5 00:41 node_exporter
-rw-r--r-- 1 3434 3434      463 Jun  5 00:50 NOTICE

启动:

./node_exporter --web.listen-address=:9200 &

8.2 配置Prometheus

下载:

wget -c https://github.com/prometheus/prometheus/releases/download/v2.14.0/prometheus-2.14.0.linux-amd64.tar.gz

解压后目录:

[root@ prometheus-2.11.1.linux-amd64]# ll
total 120288
drwxr-xr-x. 2 3434 3434     4096 Jul 10 23:26 console_libraries
drwxr-xr-x. 2 3434 3434     4096 Jul 10 23:26 consoles
drwxr-xr-x. 3 root root     4096 Nov 30 12:55 data
-rw-r--r--. 1 3434 3434    11357 Jul 10 23:26 LICENSE
-rw-r--r--. 1 root root       35 Aug  7 23:19 node.yml
-rw-r--r--. 1 3434 3434     2770 Jul 10 23:26 NOTICE
-rwxr-xr-x. 1 3434 3434 76328852 Jul 10 21:53 prometheus
-rw-r--r--  1 3434 3434     1864 Sep 21 09:36 prometheus.yml
-rwxr-xr-x. 1 3434 3434 46672881 Jul 10 21:54 promtool

在​​prometheus.yml​​加如下配置,以取数据:

  - job_name: 's1'
    static_configs:
    - targets: ['172.17.211.143:9200']

启动:

./prometheus --config.file=prometheus.yml &

8.3 配置Grafana

① 配置数据源

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

② 配置node_exporter模板

如选择官方模板(ID:11074)的展示:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

8.4 数据逻辑

做性能测试和分析,最重要是知道数据来源和含义。

如上图CPU使用率,点击title上的edit,看语句:

avg(irate(node_cpu_seconds_total{instance=~"$node",mode="system"}[30m])) by (instance)
avg(irate(node_cpu_seconds_total{instance=~"$node",mode="user"}[30m])) by (instance)
avg(irate(node_cpu_seconds_total{instance=~"$node",mode="iowait"}[30m])) by (instance)
1 - avg(irate(node_cpu_seconds_total{instance=~"$node",mode="idle"}[30m])) by (instance)

都是从Prometheus取出的数据,SQL读Prometheus中​​node_cpu_seconds_total​​的不同的模块数据。

看​​node_exporter​​暴露的计数器:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

值和top一样,都来自​/proc/​目录。如下即是top命令的数据:

最强性能监控工具之Grafana+Prometheus+Exporters-鸿蒙开发者社区

因此,os中监控数据的取值逻辑:

  • 从os本身的计数器取值
  • 传给Prometheus
  • 再由Grafana中的query语句查出相应的数据
  • 最后由Grafana展示

9 总结

为何专门解释数据的逻辑?有人说有Prometheus+Grafana+Exportor,就无需再手工执行命令。

但监控平台取的所有的数据,必然是被监控者可提供的数据,像node_exporter这样小巧的监控收集器,可获取的监控数据,并非整个系统全部的性能数据,只是取到常见计数器。

这些计数器不管用命令查看,还是用花里胡哨的工具,它的值本身都不会变。所以不管在监控平台 or 命令行中看到的数据,最重要是知道含义及这些值的变化对性能测试和分析的下一步的影响。

JMeter如何把数据推送到Grafana中?

1.在JMeter中启用插件:要将JMeter数据推送到Grafana中,您需要在JMeter中启用插件。在JMeter的lib/ext目录中找到JMeter插件管理器插件文件(JMeterPlugins-Manager.jar),并将其放置在该目录中。重启JMeter后,单击“选项”菜单中的“插件管理器”,然后选择“可选插件”选项卡。在这里,选择“grafana-backendlistener”并单击“应用更改”。

2.配置Grafana:打开Grafana中的数据源列表,选择一个数据源(例如InfluxDB)并创建一个数据库。请确保将数据库名称、用户名和密码配置为与JMeter对接的数据源的名称、用户名和密码相同。

3.在JMeter中添加Backend Listener:在JMeter测试计划中添加Backend Listener。在Backend Listener的属性中,选择“InfluxDBBackendListenerClient”作为Backend Listener实现,并按照屏幕上的说明设置InfluxDB的服务器和端口。

4.在Grafana中查看测试结果:创建一个Grafana仪表板,并选择InfluxDB作为数据源。在仪表板上选择一个面板,并将其设置为在Grafana中显示JMeter测试结果的数据。

都是监控os计数器,监控平台的数据和监控命令中的数据啥区别?

1.监控平台是一个基于web或客户端的可视化平台,可以将实时的OS监控指标以图表、表格等形式展示出来,以便于管理员进行查看与分析。

2.监控命令是一种命令行方式的工具,提供了丰富的OS监控指标查询和分析功能。它通过在终端输入不同的命令参数,实时获取和显示各种系统统计和性能指标。它主要用于开发和运维人员进行诊断和分析。

3.监控平台是一种可配置、可扩展的监控方案,它可以帮助管理员实现对复杂的分布式应用的监控。而监控命令通常只能监控单个系统的指标。

4.监控平台通常要安装一个客户端,以便向平台发送数据。而在监控命令中,可以直接在终端输入命令,获取OS的监控指标。

综上:

  • 监控平台提供GUI,便于管理员查看和管理指标数据
  • 监控命令则更灵活,提供更多细节和具体信息


文章转载自公众号: JavaEdge

分类
标签
已于2023-6-1 11:58:34修改
收藏
回复
举报
回复
    相关推荐