SpringCloud微服務實戰——搭建企業級開發框架(四十五):【微服務監控告警實現方式二】使用Actuator(Micrometer)+Prometheus+Grafana實現完整的微服務監控

2022-07-29 15:00:41

  無論是使用SpringBootAdmin還是使用Prometheus+Grafana都離不開SpringBoot提供的核心元件Actuator。提到Actuator,又不得不提Micrometer,從SpringBoot2.x開始,Actuator的功能實現都是基於Micrometer的。
  Micrometer通過儀表使用者端為各種健康監控系統提供了一個簡單的外觀Facade(Facade模式是23種設計模式中的一種,也叫外觀模式 / 門面模式,Facade(外觀)模式為子系統中的各類(或結構與方法)提供一個簡明一致的介面,隱藏子系統的複雜性,使子系統更加容易使用。它是為子系統中的一組介面所提供的一個一致的介面。)。類似於SLF4J,我們可以自由選擇log4j2、logback等紀錄檔框架一樣,Micrometer支援靈活切換或者多種並存的健康監控系統檢測基於 JVM 的應用程式。

  Micrometer提供的功能:

  • 尺寸指標(Dimensional Metrics):Micrometer 為計時器、儀表、計數器、分佈摘要和長任務計時器提供了與供應商無關的介面,具有維度資料模型,當與維度監控系統配對時,允許有效存取特定命名的度量,並具有向下鑽取的能力跨越其維度。
  • 預設定繫結(Pre-configured Bindings):開箱即用的快取、類載入器、垃圾收集、處理器利用率、執行緒池等工具,更適合可操作的洞察力。
  • Spring整合(Integrated into Spring):Micrometer 是一個檢測庫,支援從 Spring Boot 應用程式交付應用程式指標。

  Micrometer支援的監控系統:

AppOptics, Azure Monitor, Netflix Atlas, CloudWatch, Datadog, Dynatrace, Elastic, Ganglia, Graphite, Humio, Influx/Telegraf, JMX, KairosDB, New Relic, Prometheus, SignalFx, Google Stackdriver, StatsD, and Wavefront.

  上文中我們說明了如何搭建Spring Boot Admin的微服務健康檢查監控系統,簡單的應用使用Spring Boot Admin即可,複雜的叢集應用建議使用Micrometer 支援的多種靈活可配的監控系統,這裡我們選擇目前使用比較廣泛的Prometheus+Grafana監控系統。
  兩種方式都能夠實現微服務的健康檢查統計展示和告警,Prometheus+Grafana在功能和介面美觀上更強大一些,並且可以檢視歷史資料,而SpringBootAdmin優點是部署十分簡單,不需要部署太多的環境軟體,本身就是一個微服務。在兩種方式的選擇上,如果是小的專案,比如單體應用,雙擊熱備,前期可以先使用SpringBootAdmin,隨著業務的發展,可以考慮使用Prometheus+Grafana。

一、Prometheus+Grafana相關介紹

1、Prometheus介紹

Prometheus: 是一款開源的系統和服務監控系統,屬於雲原生計算基金會專案。它可以通過設定的時間間隔從設定的目標系統採集指標資料,儲存指標資料(時序資料庫),評估規則表示式,顯示結果,並在檢測到指定條件時觸發警報。

  • 多維資料模型:Prometheus 實現了一個高維資料模型,它從根本上將所有資料儲存為時間序列:屬於同一指標和同一組標記維度的時間戳值。 除了儲存的時間序列,Prometheus 可能會生成臨時派生的時間序列作為查詢的結果。
  • 高效儲存:Prometheus 以高效的自定義格式將時間序列儲存在記憶體和本地磁碟上(內建TSDB資料庫,同時也提供了遠端儲存介面),擴充套件是通過功能分片和聯合來實現的。
  • PromQL:一種強大且靈活的查詢語言,PromQL 允許對收集的時間序列資料進行切片和切塊,以生成臨時圖形、表格和警報。
  • 不依賴分散式儲存,操作簡單:每臺伺服器的可靠性都是獨立的,僅依賴於本地儲存。用 Go 編寫,所有二進位制檔案都是靜態連結的,易於部署。
  • HTTP拉取模型: 通過抓取HTTP端點採集時序資料。
  • 通過用於批次處理作業的中間閘道器支援推播時間序列資料。
  • 通過服務發現或靜態設定發現目標。
  • 出色的視覺化:Prometheus 有多種資料視覺化模式,內建表示式瀏覽器、Grafana 整合和控制檯模板語言。
  • 支援分層和水平聯合。
2、Grafana介紹

雖然Prometheus也支援視覺化介面展示,但是介面不美觀,更多人選擇使用Grafana來展示Prometheus的監控資料。

Grafana:Grafana是一款開源的資料視覺化工具。它提供對資料指標的查詢、視覺化和告警,它可以實現無論資料儲存在哪裡,都可以與您的團隊建立、探索和共用十分美觀的儀表盤資料視覺化,並培養資料驅動的文化。

  • 視覺化:具有多種選項的快速靈活的使用者端圖表。面板外掛提供了許多不同的方式來視覺化指標和紀錄檔。
  • 動態儀表板:使用在儀表板頂部顯示為下拉選單的模板變數建立動態和可重複使用的儀表板。
  • 探索指標:通過即席查詢(是使用者根據自己的需求,靈活的選擇查詢條件,系統能夠根據使用者的選擇生成相應的統計報表)和動態鑽取探索您的資料。拆分檢視並並排比較不同的時間範圍、查詢和資料來源。
  • 探索紀錄檔:體驗從指標切換到帶有保留標籤過濾器的紀錄檔的魔力。快速搜尋所有紀錄檔或實時流式傳輸它們。
  • 告警:為您最重要的指標直觀地定義告警規則。Grafana 將持續評估並向 Slack、PagerDuty、VictorOps、OpsGenie 等系統傳送通知。
  • 混合資料來源:在同一個圖中混合不同的資料來源!您可以基於每個查詢指定資料來源。這甚至適用於自定義資料來源。

二、使用Docker安裝設定Prometheus+Grafana

  我們使用Docker來安裝需要的Prometheus+Grafana,通常情況下,我們會根據業務需求來安裝需要的元件,在這裡健康監控系統也是這樣,如果我們的微服務部署在Docker容器中,那麼我們需要安裝cAdvisor元件來監控Docker相關資料指標,如果要採集系統環境資料,那麼需要安裝 Node Exporter 元件,而且告警元件也是和Prometheus分開的,如果需要告警功能,同樣需要安裝Alertmanager元件,這一連串元件的組合,自然讓我們想到使用docker-compose來安裝我們需要所有元件。
   參考 https://github.com/stefanprodan/dockprom 我們編寫兩個docker-compose檔案:

  • 伺服器端:資料採集、展示、告警,安裝 prometheus、grafana、cadvisor、alertmanager、node-exporter、caddy
  • 使用者端: 只需安裝 cadvisor、node-exporter用於採集本機資料。
1、準備Docker宿主主機的安裝部署目錄。
# 建立prometheus掛在目錄
mkdir /data/monitor/prometheus
cd /data/monitor/prometheus
touch prometheus.yml
mkdir /data/monitor/prometheus_data

# 建立alertmanager掛在目錄
mkdir -p /data/monitor/alertmanager

# 建立grafana掛在目錄
mkdir -p /data/monitor/grafana_data
mkdir -p /data/monitor/grafana/provisioning/dashboards
mkdir -p /data/monitor/grafana/provisioning/datasources
2、編寫docker-compose-prometheus-server.yml,此處為服務編排模板參考,因某些原因docker映象倉庫無法存取,需切換到能夠存取到的映象倉庫。
  • docker-compose-prometheus-server.yml
  version: '3.2'

networks:
  monitor-net:
    driver: bridge

volumes:
    prometheus_data: {}
    grafana_data: {}

services:

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - /data/monitor/prometheus:/etc/prometheus
      - /data/monitor/prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
      - '--storage.tsdb.retention.time=200h'
      - '--web.enable-lifecycle'
    restart: unless-stopped
    expose:
      - 9090
    networks:
      - monitor-net
    labels:
      org.label-schema.group: "monitoring"

  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    volumes:
      - /data/monitor/alertmanager:/etc/alertmanager
    command:
      - '--config.file=/etc/alertmanager/config.yml'
      - '--storage.path=/alertmanager'
    restart: unless-stopped
    expose:
      - 9093
    networks:
      - monitor-net
    labels:
      org.label-schema.group: "monitoring"

  nodeexporter:
    image: prom/node-exporter:latest
    container_name: nodeexporter
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.rootfs=/rootfs'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    restart: unless-stopped
    expose:
      - 9100
    networks:
      - monitor-net
    labels:
      org.label-schema.group: "monitoring"

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    privileged: true
    devices:
      - /dev/kmsg:/dev/kmsg
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker:/var/lib/docker:ro
      #- /cgroup:/cgroup:ro #doesn't work on MacOS only for Linux
    restart: unless-stopped
    expose:
      - 8080
    networks:
      - monitor-net
    labels:
      org.label-schema.group: "monitoring"

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    volumes:
      - /data/monitor/grafana_data:/var/lib/grafana
      - /data/monitor/grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards
      - /data/monitor/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
    environment:
      - GF_SECURITY_ADMIN_USER=${ADMIN_USER:-admin}
      - GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin}
      - GF_USERS_ALLOW_SIGN_UP=false
    restart: unless-stopped
    expose:
      - 3000
    networks:
      - monitor-net
    labels:
      org.label-schema.group: "monitoring"

  pushgateway:
    image: prom/pushgateway:latest
    container_name: pushgateway
    restart: unless-stopped
    expose:
      - 9091
    networks:
      - monitor-net
    labels:
      org.label-schema.group: "monitoring"

  caddy:
    image: caddy:latest
    container_name: caddy
    ports:
      - "3000:3000"
      - "9090:9090"
      - "9093:9093"
      - "9091:9091"
    volumes:
      - ./caddy:/etc/caddy
    environment:
      - ADMIN_USER=${ADMIN_USER:-admin}
      - ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin}
      - ADMIN_PASSWORD_HASH=${ADMIN_PASSWORD_HASH:-JDJhJDE0JE91S1FrN0Z0VEsyWmhrQVpON1VzdHVLSDkyWHdsN0xNbEZYdnNIZm1pb2d1blg4Y09mL0ZP}
    restart: unless-stopped
    networks:
      - monitor-net
    labels:
      org.label-schema.group: "monitoring"

在伺服器端安裝執行安裝命令:

docker-compose -f docker-compose-prometheus-server.yml up -d

執行會報錯,因無法存取部分docker映象庫:Error response from daemon: Get "https://gcr.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers),請自行設定將docker切換到能夠存取的雲伺服器。

3、編寫docker-compose-prometheus-client.yml,此處為服務編排模板參考,因某些原因docker映象倉庫無法存取,需切換到能夠存取到的映象倉庫。
version: '3.2'

services:

  nodeexporter:
    image: prom/node-exporter:latest
    container_name: nodeexporter
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.rootfs=/rootfs'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    restart: unless-stopped
    network_mode: host
    labels:
      org.label-schema.group: "monitoring"

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    privileged: true
    devices:
      - /dev/kmsg:/dev/kmsg
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /cgroup:/cgroup:ro
    restart: unless-stopped
    network_mode: host
    labels:
      org.label-schema.group: "monitoring"

在伺服器端安裝執行安裝命令:

docker-compose -f docker-compose-prometheus-server.yml up -d

同在伺服器端執行一樣,這裡執行會報錯,請自行切換可以存取到的映象倉庫。

4、以上為生產環境所需的安裝方式設定參考,下面我們使用Docker進行最小安裝,來測試執行Prometheus+Grafana。
  • 執行安裝Prometheus
docker run -d \
    --restart=always \
    -u root \
    --name prometheus \
    -p 9090:9090 \
    -v /etc/localtime:/etc/localtime \
    -v /data/monitor/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
    -v /data/monitor/prometheus_data:/prometheus \
    prom/prometheus
  • 執行安裝Grafana
docker run -d \
    --restart=always \
    -u root \
    --name grafana \
    -p 3000:3000 \
    -v /data/grafana_data:/var/lib/grafana \
    -v /data/grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards \
    -v /data/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources \
    -e GF_SECURITY_ADMIN_USER=${ADMIN_USER:-admin} \
    -e GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin} \
    -e GF_USERS_ALLOW_SIGN_UP=false \
    grafana/grafana
5、安裝成功後存取連結檢視是否成功

三、微服務相關設定及新增Prometheus支援

1、在gitegg-platform-bom工程中引入micrometer的prometheus依賴包。

請注意,在選擇micrometer-registry-prometheus版本時,一定要和框架中SpringBoot引入的micrometer相匹配的版本,否則不相容。

......
        <!-- prometheus 微服務監控 和 spring-boot-admin二選一-->
        <micrometer.registry.prometheus.version>1.5.14</micrometer.registry.prometheus.version>
......
            <!-- actuator prometheus 健康檢查https://mvnrepository.com/artifact/io.micrometer/micrometer-registry-prometheus -->
            <dependency>
                <groupId>io.micrometer</groupId>
                <artifactId>micrometer-registry-prometheus</artifactId>
                <version>${micrometer.registry.prometheus.version}</version>
            </dependency>
......
2、gitegg-cloud工程的父pom.xml統一引入prometheus依賴包,這樣,我們就可以統一靈活切換使用的監控系統。
        <!-- 如果使用prometheus進行健康檢查,這裡統一引入依賴。如果使用SpringBootAdmin,這裡註釋掉。-->
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>
3、修改Nacos,開啟prometheus抓取端點。

metrics.tags.application: ${spring.application.name} 設定tag方便Prometheus抓取資料時區分不同的服務。

# 效能監控端點設定
management:
  security:
    enabled: true
    role: ACTUATOR_ADMIN
  endpoint:
    health:
      show-details: always
  endpoints:
    enabled-by-default: true
    web:
      base-path: /actuator
      exposure:
        include: '*'
metrics:
    tags:
      application: ${spring.application.name}
    export:
      prometheus:
        enabled: true
  server:
    servlet:
      context-path: /actuator
  health:
    mail:
      enabled: false
4、檢視啟動結果 http://127.0.0.1:8002/actuator/prometheus

四、設定Prometheus+Grafana採集並展示微服務健康監控資料

1、編輯prometheus組態檔prometheus.yml,設定採集微伺服器端點
scrape_configs:
  - job_name: 'actuator-gitegg'
    basic_auth:
      username: user
      password: password
    scrape_interval: 15s
    scrape_timeout: 10s
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['192.168.0.2:80','192.168.0.2:8002']
  • basic_auth:設定採集端點的basic認證資訊
  • metrics_path:設定prometheus採集端點的路徑
  • static_configs.targets: 設定prometheus採集端點的地址
2、重啟prometheus,存取介面status -> targets,檢視採集端點狀態。

3、設定Grafana,新增prometheus資料來源並展示JVM監控圖表。


  • Import 儀表盤,Grafana提供了很多內建的儀表盤模板,官方模板地址:https://grafana.com/grafana/dashboards , 我們這裡選擇使用JVM (Micrometer)模板,輸入模板的地址https://grafana.com/grafana/dashboards/4701或者模板的編號4701,然後點選Load進行載入。

  • 執行import後就可以看到我們匯入的儀表盤模板了,點選右上角的Save進行儲存。

  通過以上步驟已經能夠搭建和設定簡單的Actuator(Micrometer)+ Prometheus + Grafana 微服務健康監控系統,檢視Prometheus / Grafana 官方檔案,我們可以知道其提供的功能非常豐富,在實際使用過程中,我們需要根據自己的業務需求進行更細維度的部署和設定。
  服務健康監控系統是保障我們系統服務正常執行的必要工具,設定部署非常方便,但是,我們生產環境一定要注意系統安全問題,不要把健康檢查的端點暴露出去,該做鑑權的做鑑權,該做安全防護的做安全防護,不要因為方便健康監控而增加安全風險。

原始碼地址:

Gitee: https://gitee.com/wmz1930/GitEgg

GitHub: https://github.com/wmz1930/GitEgg