prometheus--监控工具

1.背景

  prometheus是一个以神名为名的工具,有"先知先觉"的寓意。prometheus是一套开源的系统监控报警框架,十分符合它的定位。它启发于 Google 的 borgmon 监控系统,由工作在 SoundCloud 的 google 前员工在 2012 年创建,作为社区开源项目进行开发,并于 2015 年正式发布。prometheus,不是一个单一工具,它是由多个组件组合起来的工具。对刚刚开始学习的同学可以先看一下这边文章,让大家对prometheus有一个基本了解: https://www.cnblogs.com/linuxk/p/12017580.html(非常推荐

2.基础架构

  

Prometheus 由多个组件组成,但是其中许多组件是可选的:

服务端:

  • Prometheus Server服务段组件,它是 Prometheus 核心组件,用于收集指标和存储时间序列数据,并提供查询接口。
  • push gateway网关组件,可以将它视为一个特殊 node_exporter 组件主要用于临时性的 jobs。由于这类 jobs 存在时间较短,可能在 Prometheus 来 pull 之前就消失了。对此Jobs定时将指标push到pushgateway,再由Prometheus Server从Pushgateway上pull,根据业务需要可配置

客户端:

  • node_exporter客户端收集器组件,用于暴露已有的第三方服务的 metrics(指标) 给 Prometheus。
  • alertmanager监控告警组件,从 Prometheus server 端接收到 alerts 后,会进行去除重复数据,分组,并路由到对收的接受方式,发出报警。常见的接收方式有:电子邮件,pagerduty,OpsGenie, webhook 等,根据业务需要可配置
  • Web UI视图组件,Prometheus内置一个简单的Web控制台,可以查询指标,查看配置信息或者Service Discovery等,实际工作中,查看指标或者创建仪表盘通常使用Grafana,Prometheus作为Grafana的数据源,根据业务需要可配置。
  • client Library客户端服务(例如Go,Python,Java等),为需要监控的服务产生相应的/metrics并暴露给Prometheus Server。目前已经有很多的软件原生就支持Prometheus,提供/metrics,可以直接使用。对于像操作系统已经不提供/metrics,可以使用exporter,或者自己开发exporter来提供/metrics服务,根据业务需要可配置

3.Prometheus获取指标方式

prometheus客户端主要由2种数据采集的方式:

pull(拉取形式):指的是客户端(被监控主机)先安装各类已有的exporters在系统上,exporters以守护进程的模式运行,并开始采集数据,exporters本身也是一个http_server,可以对http请求作出响应,并返回K/V数据,也就是metrics。prometheus通过用pull的方式(HTTP_GET)去访问每个节点上的exporter并采集回需要的数据。

push(推送的形式):指的是客户端(或服务端)安装官方的pushgateway插件,然后通过我们自行编写的各种脚本,将监控数据组织成K/V的形式(metrics形式)发送给pushgateway,而后pushgateway再推送给prometheus,这里需要注意的是pushgateway不一定要安装在被监控端,也可以安装在服务端,甚至是一台不相关的主机上,换句话来说,它只是一个中间转发的媒介。 

4.执行流程

 short_lived:  就是本地自定义脚本,它会定时将指标信息推送到pushgateway。感觉pushgateway就是一个特殊的node_exporter。具体使用方式:http://www.linuxe.cn/post-506.html

5.metrics指标类型

Counter:  counter 是一个累积计数的指标,仅支持增加或者重置为0(只增不减 )。例如:可以用来统计服务请求的数量,任务完成数量,或者出错的数量。

Gauge:  gauge是一个纯数值型的能够经常进行增加或者减少的指标。例如用来做温度的计数,内存的使用,同样也可以用来使用计算服务请求数量。

Histogram:直方图,histogram 在一段时间内进行采样,并能够对指定区间以及总数进行统计.

Summary: summary与histogram类似,用于表示一段时间内的采样数据,但它直接存储了分位数,而不是通过区间来计算。

6.埋点

 spring-actuator做度量统计收集,使用Prometheus(普罗米修斯)进行数据收集,Grafana(增强ui)进行数据展示,用于监控生成环境机器的性能指标和业务数据指标。一般,我们叫这样的操作为”埋点”。SpringBoot中的依赖spring-actuator中集成的度量统计API使用的框架是Micrometer,官网是Micrometer.io。

1. 引入Prometheus metrics 包

<!-- https://mvnrepository.com/artifact/io.micrometer/micrometer-core -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.6.6</version>
</dependency>

2. 以使用http client 为例。 

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;

/**
 * 
 * @date 2021-04-29 2:59 下午
 */
public class Test3 {

    private static final MeterRegistry registry = new SimpleMeterRegistry();

    public static void main(String[] args) {
        String[] tags = formattedTag(builderTag());

        //折线图
        new Test3().counter("HTTP_SUCCESS_COUNT","http请求成功次数",tags);

        //折线图
        new Test3().timer("RT",10000L,"http请求响应时间",tags);

        //树状图
        GaugeDemo gaugeDemo = new GaugeDemo();
        gaugeDemo.setGaugeMetricsName("xxxx");
        gaugeDemo.setMetrics(1);
        new Test3().gauge("Memory_metrics_test",gaugeDemo,"内存变化指标",tags);

        // 响应成功占比 : 饼状图
        new Test3().summary("summary_http_success",0.98d,"响应成功占比",100,tags);
    }

    /**
     * 使用者也可以自行继承MeterRegistry去实现自定义的MeterRegistry。SimpleMeterRegistry适合做调试的时候使用,它的简单使用方式如下
     * @param name 指标key
     * @param desc 基础单位
     * @param tags 标签信息
     * 折线图
     */
    private void counter(String name,String desc,String... tags){
        Counter counter = Counter.builder(name)
                .description(desc)
                //标签
                .tags(tags)
                //绑定的MeterRegistry
                .register(registry);
        //数值加一,原子操作
        counter.increment();

    }

    /**
     * 时间埋点
     * @param name 指标key
     * @param nanoSeconds 响应时间
     * @param desc 描述
     * @param tags 标签信息
     * 折线图
     */
    private void timer(String name,Long nanoSeconds,String desc,String... tags){
        Timer timer = Timer.builder(name)
                .description(desc)
                //标签
                .tags(tags)
                //绑定的MeterRegistry
                .register(registry);
        //数值加一,原子操作
        timer.record(nanoSeconds, TimeUnit.NANOSECONDS);
    }

    /**
     * 数值埋点是个 Gauge, 可以用在查看某个场景单位时间内的变化的情形。
     * 树状图
     * @param name 指标key
     * @param gaugeDemo 指标对象
     * @param desc 指标描述信息
     * @param tags 标签信息
     */
    private void gauge(String name,GaugeDemo gaugeDemo,String desc,String... tags){
        Gauge gauge = Gauge.builder(name,gaugeDemo,GaugeDemo::getMetrics)
                .description(desc)
                //标签
                .tags(tags)
                //绑定的MeterRegistry
                .register(registry);

    }

    /**
     * Summary(摘要)主要用于跟踪事件的分布,在Micrometer中,对应的类是DistributionSummary(分发摘要)。它的使用方式和Timer十分相似,但是它的记录值并不依赖于时间单位。
     * 饼状图
     * 例如: 某个指标的百分比
     * @param name 指标key
     * @param desc 描述信息
     * @param scale 将记录到分布摘要的值乘以比例因子。 可配置
     * @param tags 标签信息
     * @param value 计算值
     */
    private void summary(String name,double value,String desc ,double scale,String... tags ){
        DistributionSummary summary = DistributionSummary
                .builder(name)
                .description(desc)
                .tags(tags)
                .scale(scale)
                .register(registry);
        summary.record(value);
    }


    private static class GaugeDemo{
        /**
         * 指标名
         */
        private String gaugeMetricsName;

        /**
         * 度量指标
         */
        private Integer metrics;

        public String getGaugeMetricsName() {
            return gaugeMetricsName;
        }

        public void setGaugeMetricsName(String gaugeMetricsName) {
            this.gaugeMetricsName = gaugeMetricsName;
        }

        public Integer getMetrics() {
            return metrics;
        }

        public void setMetrics(Integer metrics) {
            this.metrics = metrics;
        }
    }

    private static String[] formattedTag(Map<String,String> tag){
        String[] result = new String[tag.size() * 2];
        int i = 0;
        for (Map.Entry<String, String> entry : tag.entrySet()){
            result[i] = entry.getKey();
            i++;
            result[i] = entry.getValue();
            i++;
        }
        return result;
    }

    private static Map<String,String> builderTag(){
        /**
         * 1、Tag的值必须不为null。
         *
         * 2、Micrometer中,Tag必须成对出现,也就是Tag必须设置为偶数个,实际上它们以Key=Value的形式存在
         */
        HashMap<String, String> tags = new HashMap<>();
        tags.put("url","wwww.baidu.com");
        tags.put("code","200");
        tags.put("method","POST");
        return tags;
    }
}

 当然,还有其他类型,有其他扩展类型。就不一一举例了。

效果显示

我们的项目是基于spring cloud组件来处理的,我们可以通过访问这个地址就可以看到我们上报给prometheus的信息

http://服务ip:服务端口/actuator/prometheus

将会得到如下信息:

-- 描述信息: 请求响应时间 指标

# HELP fusion_http_response_time_seconds response.time
-- 统计的类型 # TYPE fusion_http_response_time_seconds summary

-- 指标key: RT ,{} 这个括号中的就是你写入的 tag 信息, 最后面一个是指标
RT
{bizCode
="0",endpoint="[GET]/actuator/health",method="GET",mode="servlet",status="200",type="",} 58331.0

7.Prometheus本地存储

TSDB

Prometheus本地储存使用它自己写的TSDB(时序数据库)

时序数据库全称为时间序列数据库。时间序列数据库主要用于指处理带时间标签(按照时间的顺序变化,即时间序列化)的数据,带时间标签的数据也称为时间序列数据。主要用于存储周期性的采集各种实时监控信息。

目录结构

./data
├── 01BKGV7JBM69T2G1BGBGM6KB12
│   └── meta.json
├── 01BKGTZQ1SYQJTR4PB43C8PD98
│   ├── chunks
│   │   └── 000001
│   ├── tombstones
│   ├── index
│   └── meta.json
├── 01BKGTZQ1HHWHV8FBJXW1Y3W0K
│   └── meta.json
├── 01BKGV7JC0RY8A6MACW02A2PJD
│   ├── chunks
│   │   └── 000001
│   ├── tombstones
│   ├── index
│   └── meta.json
└── wal
    ├── 00000002
    └── checkpoint.00000
首先,block 在这里是一个数据块,每个数据块相对独立,由一个目录组成,该目录里包含:一个或者多个 chunk 文件(保存 timeseries 数据)、一个 metadata文件、一个 index 文件(通过 metric name 和 labels 查找 timeseries 数据在 chunk 文件的位置)。

储存原理(write)

Prometheus 按2小时一个 block 进行存储,最新写入的数据保存在内存 block 中,达到2小时后写入磁盘。为了防止程序崩溃导致数据丢失,实现了 WAL(write-ahead-log)机制,启动时会以写入日志(WAL)的方式来实现重播,从而恢复数据。

8.其他监控工具对比

引用

https://www.sohu.com/a/342733264_198222

https://www.cnblogs.com/linuxk/p/12017580.html

http://www.linuxe.cn/post-506.html

https://www.freesion.com/article/5362527244/

https://www.jianshu.com/p/a80cc630fa73

原文地址:https://www.cnblogs.com/Zero-Jo/p/14714669.html