简单介绍Prometheus

一、什么是Prometheus?

Prometheus是一套开源的监控与告警系统,基于Golang实现,可用于对集群的状态进行实时的监控。如今很多的公司与组织都在使用Prometheus,项目具有非常成熟的开发者社区。

github上star数量为33.4k
prometheus提供的Web界面

二、Prometheus的启动?

1、下载Prometheus,选择合适的版本,我选择的是prometheus-2.17.0-rc.0.linux-amd64。https://prometheus.io/download/

2、配置prometheus路径下的prometheus.yml文件,我们可以在global中配置包括prometheus抓取数据、验证rule的时间间隔;在rule_files中配置rule_file的地址;scrape_configs中设置数据源。

global:
  # How frequently to scrape targets by default.
  [ scrape_interval: <duration> | default = 1m ]

  # How long until a scrape request times out.
  [ scrape_timeout: <duration> | default = 10s ]

  # How frequently to evaluate rules.
  [ evaluation_interval: <duration> | default = 1m ]

  # The labels to add to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
  external_labels:
    [ <labelname>: <labelvalue> ... ]

# Rule files specifies a list of globs. Rules and alerts are read from
# all matching files.
rule_files:
  [ - <filepath_glob> ... ]

# A list of scrape configurations.
scrape_configs:
  [ - <scrape_config> ... ]

# Alerting specifies settings related to the Alertmanager.
alerting:
  alert_relabel_configs:
    [ - <relabel_config> ... ]
  alertmanagers:
    [ - <alertmanager_config> ... ]

# Settings related to the experimental remote write feature.
remote_write:
  [ - <remote_write> ... ]

# Settings related to the experimental remote read feature.
remote_read:
  [ - <remote_read> ... ]

3、输入./prometheus,启动prometheus服务。prometheus的默认端口为9090,通过访问http://localhost:9090即可进入prometheus的Web界面。

三、架构

image

数据收集:

Prometheus收集方式有两种方式,分别为pull和push。
1、若以pull的的方式,prometheus提供了Golang、Java、Scala、Python、Ruby等语言的客户端库,在这里我简单介绍一下Go中的用法。

package main

import (
    "fmt"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
    "math"
    "math/rand"
    "net/http"
    "time"
)

var (
    TestCounter = prometheus.NewCounter(prometheus.CounterOpts{
        Name: "test_counter",
        Help: "test_counter",
    })
    TestGauge = prometheus.NewGauge(prometheus.GaugeOpts{
    Name: "test_gauge",
    Help: "test_gauge",
    })
    TestHistogram = prometheus.NewHistogram(prometheus.HistogramOpts{
    Name: "test_histogram",
    Help: "test_histogram",
    Buckets: prometheus.LinearBuckets(20, 5, 5),
    })
    TestSummary = prometheus.NewSummary(prometheus.SummaryOpts{
    Name: "test_summary",
    Help: "test_summary",
    Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
    })
)

func main() {
    prometheus.MustRegister(TestGauge)
    prometheus.MustRegister(TestHistogram)
    prometheus.MustRegister(TestSummary)
    prometheus.MustRegister(TestCounter)
    
    go func(){
        i := 0.0
        for {
            TestGauge.Add(1)
            TestCounter.Add(1)
            TestHistogram.Observe(30 + math.Floor(float64(rand.Intn(120))*math.Sin(i*0.1))/10)
            TestSummary.Observe(30 + math.Floor(float64(rand.Intn(120))*math.Sin(i*0.1))/10)
            time.Sleep(2 * time.Second)
            i += 1
        }
    }()
    http.Handle("/metrics", promhttp.Handler())
    err := http.ListenAndServe("localhost:2112", nil)
    if err != nil {
        fmt.Println(err)
    }
}

首先我们创建prometheus中的数据类型,包括Counter、Gauge、Histogram、Summary等,对它们感兴趣的可以查看https://prometheus.io/docs/concepts/metric_types/,接着将创建好的变量register到prometheus中并提供端口给prometheus来pull数据即可,这里需要我们在前面所提到的prometheus.yml文件中配置好数据源。

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'
    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.
    static_configs:
    - targets: ['localhost:9090']
  - job_name: 'myapp'
    static_configs:
    - targets: ['localhost:2112']

2、若以push的方式,则需要Pushgateway作为数据的收集器。首先我们需要下载Pushgateway https://prometheus.io/download/,解压后到pushgateway的路径下./pushgateway启动服务,默认端口为9091。当然,我们需要和前面pull时一样,在prometheus.yml文件中配置pushgateway的地址,这里不再赘述。
接着,将我们想要发送到Prometheus的数据通过http的方式发送到pushgateway。

func main() {
    ticker := time.NewTicker(2 * time.Second)
    for range ticker.C{
        for i := 1; i < 6; i++ {
            cmd := exec.Command("bash", "-c",
                "curl -XPOST --data-binary @job" + strconv.Itoa(i) + ".txt localhost:9091/metrics/job/" + strconv.Itoa(i))
            err := cmd.Start()
            if err != nil {
                fmt.Println(err)
            }
            fmt.Println("sending data")
        }
    }
}

代码使用了curl将数据发送到Pushgateway,job文件里的数据格式如下

slot{label1="xxx", label2="xxx"} 0

这是Prometheus中数据的最基本格式,这样的数据称为一个metrics,其中“slot”是该metrics的name;{}中包括了metrics的label,这些label是辨别不同metrics的标志,在通过PromQL检索时需要使用;而0则是该metrics的value,value随时间的变化而变化,metrics为时间序列数据,旧数据将存储在prometheus实现的TSDB中。

Prometheus server

这里主要介绍Prometheus的TSDB和HTTP server

TSDB

首先介绍数据在磁盘中的结构

-bash-4.2$ tree data
data
├── 01EQWQPHYCYQV25DGKWDXX01P5    #block
│   ├── chunks
│   │   └── 000001  #compressed time series data
│   ├── index  #query index
│   ├── meta.json  #record block meta information
│   └── tombstones # temporarily tore deleted records
├── lock
├── queries.active
└── wal  #write ahead log, prevent data loss
    ├── 00001561
    ├── 00001562
    ├── 00001563
    ├── 00001564
    └── checkpoint.001560
        └── 00000000

时序数据以block为单位持久化在磁盘里,每个block存在chunks、index、meta.json、tombstones等文件,其中
1、meta.json存储了Block的元数据信息,包括Block的时间窗口、包含数据的数量、压缩的次数等。
2、chunks包含了时间窗口内的所有samples,是实际存储数据的文件。
3、tombstones是暂存被删除数据的文件,metrics被删除时不会立刻从block中剔除,而是在tombstones中标记,直到block中metrics全被删除或者block被压缩时真正删除metrics。
4、index文件是用户查询数据时所依赖的索引文件。
5、wal的作用是防止数据丢失,当prometheus意外崩溃时,重启会首先将wal中数据读入内存。


block持久化的流程

每一个block可以看作一个小型数据库,其中index文件则是其索引,它使用了倒排索引,提高了Prometheus的查找效率。

┌────────────────────────────┬─────────────────────┐
│ magic(0xBAAAD700) <4b>     │ version(1) <1 byte> │
├────────────────────────────┴─────────────────────┤
│ ┌──────────────────────────────────────────────┐ │
│ │            1.     Symbol Table                 │ │
│ ├──────────────────────────────────────────────┤ │
│ │            2.       Series                    │ │
│ ├──────────────────────────────────────────────┤ │
│ ├──────────────────────────────────────────────┤ │
│ │            3.       Postings 1                 │ │
│ ├──────────────────────────────────────────────┤ │
│ │                      ...                     │ │
│ ├──────────────────────────────────────────────┤ │
│ │                   Postings N                 │ │
│ ├──────────────────────────────────────────────┤ │
│ ├──────────────────────────────────────────────┤ │
│ │            4.     Postings Table               │ │
│ ├──────────────────────────────────────────────┤ │
│ │            5.         TOC                     │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘

1、toc:index 文件中各部分的起始 offset;
2、postings offset table: 每个entry都保存了一对label的key和value以及对应series list在posting中offset;
3、posting: 每一个label pair都将对应一个series list;(真正存储series id list的地方)
4、series: 记录了这个block里有哪些series,series的各个label(symbol table中已编号),每个series里有哪些chunk,每个chunk的开始时间和结束时间;
5、symbol table: 存储block中所有series的Label key与Label value,并对它们编号,作用是压缩index文件的大小。


索引的流程

HTTP Server

下面是Prometheus提供的一些HTTP API:
Instant queries: /api/v1/query?query=up&time=xxx
Range queries: /api/v1/query_range?query=up&start=xxx&end=xxx&step=xxx
Querying metadata: /api/v1/series
Getting label names: /api/v1/labels
Targets: /api/v1/targets
Rules: /api/v1/rules
Alerts: /api/v1/alerts
TSDB Admin: /api/v1/admin/tsdb (Snapshot,Delete Series,Clean Tombstones)
详情可以看:https://prometheus.io/docs/prometheus/latest/querying/api/

除了在prometheus的web界面进行操作,还可以直接通过http去调用Prometheus的API,获取想要的数据。这里简单介绍一下这些API的用法,
1、前两个分别是瞬时查询、范围查询,通过设置metrics name和时间,得到queries的结果。
2、Querying metadata返回符合label的series的信息,将metrics作为搜索条件可以查找所有对应的series信息。
3、Getting label names可以返回所有的Label值。
4、返回所有prometheus的targets,包括prometheus自身、pushgateway、node exporter等等。
5、Rules可以查看prometheus配置中的报警规则。使用PromQL完成报警规则的设置。
6、Alert可以返回所有的报警信息。
7、TSDB admin api暴露了操作数据的方法,需要在prometheus中设置 —web.enable-admin-api才可以使用这些api,Snapshot的功能是为当前的数据创建一个快照,并返回数据所在的路径;Delete Series可以删除指定的series,prometheus中被删除的数据会被放在Tomstones中,直到Block被压缩时才会删除tomstones中的数据,当然也可以调用clean tombstones接口来清理tomstones的数据。

PromQL

Prometheus提供了PromQL来对tsdb中的数据进行查询。在Prometheus的Web界面和Grafana中都能输入PromQL进行查询。基础的用法是输入metrics名字与对应想要的label,就能搜索到对应的时序数据。https://prometheus.io/docs/prometheus/latest/querying/basics/#functions

Grafana中输入PromQL

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容