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

核心組件

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

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

WX20190118-145432@2x.png

架構(gòu)邏輯

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

Metric類型

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

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

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

Gauge:可增可減的儀表盤

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

Summary 摘要

  • 類似于 Histogram, 典型的應(yīng)用如:請求持續(xù)時間,響應(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

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

Histogram 直方圖

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

舉例:

# 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指標直接反應(yīng)了在不同區(qū)間內(nèi)樣本的個數(shù),區(qū)間通過標簽len進行定義,sum是總數(shù),count是次數(shù)。

Summary與Histogram不同

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

PromQL

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

Prometheus報警

WX20190118-161507@2x.png

Prometheus報警簡單可以分為:

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

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

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

AlertManager

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

集群及高可用

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

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

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 # 臨時的label
      action:        hashmod # 使用取模方法
    - source_labels: [__tmp_hash]
      regex:         ^1$ # 取哪個模
      action:        keep # 可用

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

聯(lián)邦集群

WX20190122-170332@2x.png

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

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

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

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

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

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

在 Prometheus 的配置中,一個最重要的概念就是數(shù)據(jù)源 target,而數(shù)據(jù)源的配置主要分為靜態(tài)配置和動態(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進行服務(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ù)平臺服務(wù)發(fā)現(xiàn)優(yōu)化
我們微服務(wù)使用Eureka并不在Prometheus的自動配置范圍內(nèi),于是我們對Eureka進行二次開發(fā),讓它偽裝成Consul的API接口提供給Prometheus接口。
參見源碼

使用Java自定義Export

添加攔截器,為監(jiā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ù)寫父方法,實現(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指標的對象則包含兩個主要的方法inc()以及dec(),用戶添加或者減少計數(shù)。在這里我們使用Gauge記錄當前正在處理的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 {
        ...省略的代碼
        // 計數(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 {
        ...省略的代碼
        // 計數(shù)器-1
        inprogressRequests.labels(requestURI, method, String.valueOf(status)).dec();

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

參考:
Prometheus 入門與實踐
Prometheus 實戰(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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

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

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