微服務(wù)實(shí)戰(zhàn)之Prometheus使用分享

Prometheus是什么?

Prometheus 是由 SoundCloud 開源監(jiān)控告警解決方案,從 2012 年開始編寫代碼,再到 2015 年 github 上開源以來,已經(jīng)吸引了 9k+ 關(guān)注,以及很多大公司的使用;2016 年 Prometheus 成為繼 k8s 后,第二名 CNCF(Cloud Native Computing Foundation) 成員。

主要功能

  • 多維 數(shù)據(jù)模型(時(shí)序由 metric 名字和 k/v 的 labels 構(gòu)成)。
  • 靈活的查詢語句(PromQL)。
  • 無依賴存儲(chǔ),支持 local 和 remote 不同模型。
  • 采用 http 協(xié)議,使用 pull 模式,拉取數(shù)據(jù),簡單易懂。
  • 監(jiān)控目標(biāo),可以采用服務(wù)發(fā)現(xiàn)或靜態(tài)配置的方式。
  • 支持多種統(tǒng)計(jì)數(shù)據(jù)模型,圖形化友好。

核心組件

  • Prometheus Server, 主要用于抓取數(shù)據(jù)和存儲(chǔ)時(shí)序數(shù)據(jù),另外還提供查詢和 Alert Rule 配置管理。
  • client libraries,客戶端庫,為需要監(jiān)控的服務(wù)生成相應(yīng)的 metrics 并暴露給 Prometheus server。當(dāng) Prometheus server 來 pull 時(shí),直接返回實(shí)時(shí)狀態(tài)的 metrics,比如Java Client。
  • push gateway ,用于批量,短期的監(jiān)控?cái)?shù)據(jù)的匯總節(jié)點(diǎn),主要用于業(yè)務(wù)數(shù)據(jù)匯報(bào)等。
  • 各種匯報(bào)數(shù)據(jù)的 exporters ,下面是兩種解釋:
    • 用于暴露已有的第三方服務(wù)的 metrics 給 Prometheus,例如匯報(bào)機(jī)器數(shù)據(jù)的 node_exporter, 匯報(bào) MongoDB 信息的 MongoDB exporter 等等。
    • 在 Prometheus 中負(fù)責(zé)數(shù)據(jù)匯報(bào)的程序統(tǒng)一叫做 Exporter, 而不同的 Exporter 負(fù)責(zé)不同的業(yè)務(wù)。 它們具有統(tǒng)一命名格式,即 xx_exporter, 例如負(fù)責(zé)主機(jī)信息收集node_exporter。Prometheus 社區(qū)已經(jīng)提供了很多 exporter, 詳情請參考這里
  • Alertmanager:從 Prometheus server 端接收到 alerts 后,會(huì)進(jìn)行去除重復(fù)數(shù)據(jù),分組,并路由到對收的接受方式,發(fā)出報(bào)警。常見的接收方式有:電子郵件 ,OpsGenie, webhook 等。

Prometheus基礎(chǔ)架構(gòu)

WX20190118-145432@2x.png

架構(gòu)邏輯

  • Prometheus server 定期從靜態(tài)配置的 targets 或者服務(wù)發(fā)現(xiàn)的 targets 拉取數(shù)據(jù)。
  • 當(dāng)新拉取的數(shù)據(jù)大于配置內(nèi)存緩存區(qū)的時(shí)候,Prometheus 會(huì)將數(shù)據(jù)持久化到磁盤(如果使用 remote storage 將持久化到云端)。
  • Prometheus 可以配置 rules,然后定時(shí)查詢數(shù)據(jù),當(dāng)條件觸發(fā)的時(shí)候,會(huì)將 alert 推送到配置的 Alertmanager。
  • Alertmanager 收到警告的時(shí)候,可以根據(jù)配置,聚合,去重,降噪,最后發(fā)送警告。
  • 可以使用 API, Prometheus Console 或者 Grafana 查詢和聚合數(shù)據(jù)。

Metric類型

Prometheus定義了4中不同的指標(biāo)類型(metric type):Counter(計(jì)數(shù)器)、Gauge(儀表盤)、Histogram(直方圖)、Summary(摘要)

Counter:只增不減的計(jì)數(shù)器

Counter類型的指標(biāo)其工作方式和計(jì)數(shù)器一樣,只增不減(除非系統(tǒng)發(fā)生重置)。常見的監(jiān)控指標(biāo),如http_requests_total。一般在定義Counter類型指標(biāo)的名稱時(shí)推薦使用_total作為后綴。

Gauge:可增可減的儀表盤

auge類型的指標(biāo)側(cè)重于反應(yīng)系統(tǒng)的當(dāng)前狀態(tài)。因此這類指標(biāo)的樣本數(shù)據(jù)可增可減。常見指標(biāo)如:node_memory_MemFree(主機(jī)當(dāng)前空閑的內(nèi)容大小)、node_memory_MemAvailable(可用內(nèi)存大小)都是Gauge類型的監(jiān)控指標(biāo)。

Summary 摘要

  • 類似于 Histogram, 典型的應(yīng)用如:請求持續(xù)時(shí)間,響應(yīng)大小;
  • 提供觀測值的 count 和 sum 功能;
  • 提供百分位的功能,即可以按百分比劃分跟蹤結(jié)果。

舉例:

# HELP prometheus_tsdb_wal_fsync_duration_seconds Duration of WAL fsync.
# TYPE prometheus_tsdb_wal_fsync_duration_seconds summary
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.5"} 0.012352463
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.9"} 0.014458005
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.99"} 0.017316173
prometheus_tsdb_wal_fsync_duration_seconds_sum 2.888716127000002
prometheus_tsdb_wal_fsync_duration_seconds_count 216

當(dāng)前Prometheus Server進(jìn)行wal_fsync操作的總次數(shù)為216次,耗時(shí)2.888716127000002s。其中中位數(shù)(quantile=0.5)的耗時(shí)為0.012352463,9分位數(shù)(quantile=0.9)的耗時(shí)為0.014458005s。

Histogram 直方圖

  • 可以理解為柱狀圖,典型的應(yīng)用如:請求持續(xù)時(shí)間,響應(yīng)大小。
  • 可以對觀察結(jié)果采樣,分組及統(tǒng)計(jì)。

舉例:

# HELP prometheus_tsdb_compaction_chunk_range Final time range of chunks on their first compaction
# TYPE prometheus_tsdb_compaction_chunk_range histogram
prometheus_tsdb_compaction_chunk_range_bucket{le="100"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="400"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="1600"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="6400"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="25600"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="102400"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="409600"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="1.6384e+06"} 260
prometheus_tsdb_compaction_chunk_range_bucket{le="6.5536e+06"} 780
prometheus_tsdb_compaction_chunk_range_bucket{le="2.62144e+07"} 780
prometheus_tsdb_compaction_chunk_range_bucket{le="+Inf"} 780
prometheus_tsdb_compaction_chunk_range_sum 1.1540798e+09
prometheus_tsdb_compaction_chunk_range_count 780

Histogram指標(biāo)直接反應(yīng)了在不同區(qū)間內(nèi)樣本的個(gè)數(shù),區(qū)間通過標(biāo)簽len進(jìn)行定義,sum是總數(shù),count是次數(shù)。

Summary與Histogram不同

不同在于Histogram通過histogram_quantile函數(shù)是在服務(wù)器端計(jì)算的分位數(shù)。 而Sumamry的分位數(shù)則是直接在客戶端計(jì)算完成。因此對于分位數(shù)的計(jì)算而言,Summary在通過PromQL進(jìn)行查詢時(shí)有更好的性能表現(xiàn),而Histogram則會(huì)消耗更多的資源。反之對于客戶端而言Histogram消耗的資源更少。在選擇這兩種方式時(shí)用戶應(yīng)該按照自己的實(shí)際場景進(jìn)行選擇。

PromQL

PromQL是Prometheus內(nèi)置的數(shù)據(jù)查詢語言,其提供對時(shí)間序列數(shù)據(jù)豐富的查詢,聚合以及邏輯運(yùn)算能力的支持。并且被廣泛應(yīng)用在Prometheus的日常應(yīng)用當(dāng)中,包括對數(shù)據(jù)查詢、可視化、告警處理當(dāng)中。
有興趣可以PromQL學(xué)習(xí)。

Prometheus報(bào)警

WX20190118-161507@2x.png

Prometheus報(bào)警簡單可以分為:

  • 定義AlertRule(告警規(guī)則),告警規(guī)則實(shí)際上主要由PromQL進(jìn)行定義,其實(shí)際意義是當(dāng)表達(dá)式(PromQL)查詢結(jié)果持續(xù)多長時(shí)間(During)后出發(fā)告警;
  • AlertManager(報(bào)警管理),Alertmanager作為一個(gè)獨(dú)立的組件,負(fù)責(zé)接收并處理來自Prometheus Server(也可以是其它的客戶端程序)的告警信息。

自定義Prometheus告警規(guī)則

groups:
- name: example 
  rules:
  - alert: HighErrorRate # 告警規(guī)則的名稱
    expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5  # 基于PromQL表達(dá)式告警觸發(fā)條件,用于計(jì)算是否有時(shí)間序列滿足該條件。
    for: 10m # 評估等待時(shí)間,可選參數(shù)。用于表示只有當(dāng)觸發(fā)條件持續(xù)一段時(shí)間后才發(fā)送告警。在等待期間新產(chǎn)生告警的狀態(tài)為pending。
    labels:
      severity: page # 自定義標(biāo)簽,允許用戶指定要附加到告警上的一組附加標(biāo)簽
    annotations:
      summary: High request latency
      description: description info

AlertManager

WX20190118-171026@2x.png
  • 分組,分組機(jī)制可以將詳細(xì)的告警信息合并成一個(gè)通知。在某些情況下,比如由于系統(tǒng)宕機(jī)導(dǎo)致大量的告警被同時(shí)觸發(fā),在這種情況下分組機(jī)制可以將這些被觸發(fā)的告警合并為一個(gè)告警通知,避免一次性接受大量的告警通知,而無法對問題進(jìn)行快速定位。
  • 抑制,抑制是指當(dāng)某一告警發(fā)出后,可以停止重復(fù)發(fā)送由此告警引發(fā)的其它告警的機(jī)制。
  • 靜默,靜默提供了一個(gè)簡單的機(jī)制可以快速根據(jù)標(biāo)簽對告警進(jìn)行靜默處理。如果接收到的告警符合靜默的配置,Alertmanager則不會(huì)發(fā)送告警通知。

集群及高可用

功能分區(qū)(高并發(fā))

考慮另外一種極端情況(網(wǎng)上有人說一臺(tái)prometheus可以支持一千個(gè)左右節(jié)點(diǎn)),即單個(gè)采集任務(wù)的Target數(shù)也變得非常巨大。這時(shí)簡單通過聯(lián)邦集群進(jìn)行功能分區(qū),Prometheus Server也無法有效處理時(shí)。這種情況只能考慮繼續(xù)在實(shí)例級(jí)別進(jìn)行功能劃分。

WX20190122-165536@2x.png
global:
  external_labels:
    slave: 1  # This is the 2nd slave. This prevents clashes between slaves.
scrape_configs:
  - job_name: some_job
    relabel_configs:
    - source_labels: [__address__] # IP
      modulus:       4 # 取模
      target_label:  __tmp_hash # 臨時(shí)的label
      action:        hashmod # 使用取模方法
    - source_labels: [__tmp_hash]
      regex:         ^1$ # 取哪個(gè)模
      action:        keep # 可用

在微服務(wù)平臺(tái),我們使用IP取模奇偶數(shù)的形式來過去微服務(wù)系統(tǒng)的監(jiān)控?cái)?shù)據(jù)。

聯(lián)邦集群

WX20190122-170332@2x.png

這種部署方式一般適用于兩種場景:

場景一:單數(shù)據(jù)中心 + 大量的采集任務(wù)

這種場景下Promthues的性能瓶頸主要在于大量的采集任務(wù),因此用戶需要利用Prometheus聯(lián)邦集群的特性,將不同類型的采集任務(wù)劃分到不同的Promthues子服務(wù)中,從而實(shí)現(xiàn)功能分區(qū)。例如一個(gè)Promthues Server負(fù)責(zé)采集基礎(chǔ)設(shè)施相關(guān)的監(jiān)控指標(biāo),另外一個(gè)Prometheus Server負(fù)責(zé)采集應(yīng)用監(jiān)控指標(biāo)。再有上層Prometheus Server實(shí)現(xiàn)對數(shù)據(jù)的匯聚。

場景二:多數(shù)據(jù)中心(微服務(wù)使用)

這種模式也適合與多數(shù)據(jù)中心的情況,當(dāng)Promthues Server無法直接與數(shù)據(jù)中心中的Exporter進(jìn)行通訊時(shí),在每一個(gè)數(shù)據(jù)中部署一個(gè)單獨(dú)的Promthues Server負(fù)責(zé)當(dāng)前數(shù)據(jù)中心的采集任務(wù)是一個(gè)不錯(cuò)的方式。這樣可以避免用戶進(jìn)行大量的網(wǎng)絡(luò)配置,只需要確保主Promthues Server實(shí)例能夠與當(dāng)前數(shù)據(jù)中心的Prometheus Server通訊即可。 中心Promthues Server負(fù)責(zé)實(shí)現(xiàn)對多數(shù)據(jù)中心數(shù)據(jù)的聚合。

Prometheus的服務(wù)發(fā)現(xiàn)

在 Prometheus 的配置中,一個(gè)最重要的概念就是數(shù)據(jù)源 target,而數(shù)據(jù)源的配置主要分為靜態(tài)配置和動(dòng)態(tài)發(fā)現(xiàn), 大致為以下幾類:

  • static_configs: 靜態(tài)服務(wù)發(fā)現(xiàn)
  • dns_sd_configs: DNS 服務(wù)發(fā)現(xiàn)
  • file_sd_configs: 文件服務(wù)發(fā)現(xiàn)
  • consul_sd_configs: Consul 服務(wù)發(fā)現(xiàn)
  • serverset_sd_configs: Serverset 服務(wù)發(fā)現(xiàn)
  • nerve_sd_configs: Nerve 服務(wù)發(fā)現(xiàn)
  • marathon_sd_configs: Marathon 服務(wù)發(fā)現(xiàn)
  • kubernetes_sd_configs: Kubernetes 服務(wù)發(fā)現(xiàn)
  • gce_sd_configs: GCE 服務(wù)發(fā)現(xiàn)
  • ec2_sd_configs: EC2 服務(wù)發(fā)現(xiàn)
  • openstack_sd_configs: OpenStack 服務(wù)發(fā)現(xiàn)
  • azure_sd_configs: Azure 服務(wù)發(fā)現(xiàn)
  • triton_sd_configs: Triton 服務(wù)發(fā)現(xiàn)

使用Consul進(jìn)行服務(wù)發(fā)現(xiàn)


![WX20190122-170332@2x.png](https://upload-images.jianshu.io/upload_images/1902234-ff0719380632188f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

Prometheus exporter配置部分:

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: 'consul-prometheus'
    consul_sd_configs:
    #consul 地址
      - server: '127.0.0.1:8500'
        services: []

微服務(wù)平臺(tái)服務(wù)發(fā)現(xiàn)優(yōu)化
我們微服務(wù)使用Eureka并不在Prometheus的自動(dòng)配置范圍內(nèi),于是我們對Eureka進(jìn)行二次開發(fā),讓它偽裝成Consul的API接口提供給Prometheus接口。
參見源碼

使用Java自定義Export

添加攔截器,為監(jiān)控埋點(diǎn)做準(zhǔn)備

繼承WebMvcConfigurerAdapter類,復(fù)寫addInterceptors方法,對所有請求/**添加攔截器

@SpringBootApplication
@EnablePrometheusEndpoint
public class SpringApplication extends WebMvcConfigurerAdapter implements CommandLineRunner {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new PrometheusMetricsInterceptor()).addPathPatterns("/**");
    }
}

PrometheusMetricsInterceptor集成HandlerInterceptorAdapter,通過復(fù)寫父方法,實(shí)現(xiàn)對請求處理前/處理完成的處理。

public class PrometheusMetricsInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }
}

以Gauge為例

對于Gauge指標(biāo)的對象則包含兩個(gè)主要的方法inc()以及dec(),用戶添加或者減少計(jì)數(shù)。在這里我們使用Gauge記錄當(dāng)前正在處理的Http請求數(shù)量。

public class PrometheusMetricsInterceptor extends HandlerInterceptorAdapter {

    ...省略的代碼
    static final Gauge inprogressRequests = Gauge.build()
            .name("io_namespace_http_inprogress_requests").labelNames("path", "method", "code")
            .help("Inprogress requests.").register();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        ...省略的代碼
        // 計(jì)數(shù)器+1
        inprogressRequests.labels(requestURI, method, String.valueOf(status)).inc();
        return super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ...省略的代碼
        // 計(jì)數(shù)器-1
        inprogressRequests.labels(requestURI, method, String.valueOf(status)).dec();

        super.afterCompletion(request, response, handler, ex);
    }
}

參考:
Prometheus 入門與實(shí)踐
Prometheus 實(shí)戰(zhàn)
Prometheus 官網(wǎng)文檔
Consul+Prometheus系統(tǒng)監(jiān)控之服務(wù)發(fā)現(xiàn)
自定義Metrics:讓Prometheus監(jiān)控你的應(yīng)用程序(Spring版)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 文章目的: 1、向沒聽過或者剛聽過但是還對這個(gè)監(jiān)控系統(tǒng)沒有任何概念的開發(fā)者介紹Prometheus的應(yīng)用場景。2、...
    whaike閱讀 39,734評論 15 59
  • 主機(jī)數(shù)據(jù)收集 主機(jī)數(shù)據(jù)的采集是集群監(jiān)控的基礎(chǔ);外部模塊收集各個(gè)主機(jī)采集到的數(shù)據(jù)分析就能對整個(gè)集群完成監(jiān)控和告警等功...
    梅_梅閱讀 6,716評論 0 7
  • 正澆著窗臺(tái)的花 一轉(zhuǎn)眼卻看到了樓下的你 放下水壺 直沖沖地奔樓下而去 我住在七樓 到了樓下 一群陌生人中卻找不見你...
    Edinburgh丶閱讀 354評論 0 0
  • 今天是我開始簡書分享的第一天,我給自己立一個(gè)Flag:從今天起,我要開始自己的寫作之路,要堅(jiān)持每周5000...
    鸞七閱讀 815評論 0 0
  • 庸庸碌碌三十載: 有希冀、有失望,有追求、有頹廢, 有奮起、有止步,有反抗、有待斃; 何嘗不想巾幗不讓須眉, 無奈...
    穿越小女子閱讀 230評論 0 0