Prometheus + Grafana 監控 SpringBoot


整體結構

SpringBootactuator 提供了監控端點。

Prometheus 是監控系統,可以從 Springboot 獲取監控數據,以時序數據的形式存儲,並提供了監控數據的查詢服務。

Grafana 是專業的 UI 儀表盤系統,支持非常多的數據源,其中就包括 Prometheus,可以便利的從中獲取數據,使用儀表盤展示出來。

springboot 2 中引入了 micrometer,它可以更方便的對接各種監控系統,包括 Prometheus。

所以整體的結構就是:

  • springboot(micrometer)產生監控數據。
  • Prometheus 獲取 springboot 應用的監控數據,存儲,並提供數據查詢服務。
  • Grafana 對接 Prometheus 數據源,調用其數據查詢服務,用專業的儀表盤 UI 進行展示。

實踐步驟

  • 創建應用 -- 作為監控目標,產生監控數據。

  • 集成度量庫 micrometer -- 以便對接監控系統 Prometheus。

  • 部署 prometheus

  • 配置 prometheus -- 監控之前創建的 springboot 應用,了解 Prometheus 的查詢服務。

  • 部署 Grafana

  • 添加 Prometheus 數據源

  • 添加 JVM 監控儀表盤 -- 展示之前 springboot 應用的 JVM 狀態。

  • 自定義監控指標 -- 自有的監控指標都是底層基礎數據,業務相關指標需要我們自己寫代碼。

  • 動態變更監控目標 -- 如果監控目標發生變動就改一次 Prometheus 的配置文件,並重新啟動,這是不適合的,需要使用動態配置的方式。

1. 創建應用 集成 micrometer

創建一個最簡的 springboot 應用,添加 micrometer 依賴。

pom.xml :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>springboot2demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springboot2demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>io.micrometer</groupId>
			<artifactId>micrometer-registry-prometheus</artifactId>
			<version>1.1.4</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

application.properties

spring.application.name=springboot2demo
# 打開所有 Actuator 服務
management.endpoints.web.exposure.include=*
# 將應用名稱添加到計量器的 tag 中去
# 以便 Prometheus 根據應用名區分不同服務
management.metrics.tags.application=${spring.application.name}

在啟動類中添加Bean,用於監控JVM性能指標:

package com.example.springboot2demo;

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Springboot2demoApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot2demoApplication.class, args);
    }

    @Bean
    MeterRegistryCustomizer<MeterRegistry> configurer(
            @Value("${spring.application.name}") String applicationName) {
        return (registry) -> registry.config().commonTags("application", applicationName);
    }
}

啟動服務。

查看監控端點信息:

2. 部署 Prometheus

官網:

https://prometheus.io/

可以下載安裝包來安裝,但下載速度極其慢,幾乎下載不了。

可以使用 docker 部署,因為國內有docker鏡像,所以速度很快。

docker 方式啟動:

$ docker run --name prometheus -d -p 127.0.0.1:9090:9090 prom/prometheus

執行完成后就OK了,可以看一下 Prometheus 的界面。

http://localhost:9090/targets 是監控目標列表頁:

http://localhost:9090/graph 是查詢控制台,也有簡單的圖表展示:

現在還沒對接應用,后面對接之后可以看到詳細的內容。

3. Prometheus + Springboot應用

監控應用,需要在 Prometheus 配置文件中添加應用的相關信息。

配置文件在容器中的路徑:/etc/prometheus

查看一下配置文件的默認內容:

$ docker exec -it [容器ID] cat /etc/prometheus/prometheus.yml

紅框內是我們要關注的部分,按照這個形式添加我們的應用即可。

需要添加的內容為:

  - job_name: 'springboot_app'
    scrape_interval: 5s
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['192.168.31.6:8080']
        "labels": {
            "instance": "springboot2-A",
            "service": "springboot2-A-service"
        }

metrics_path 指定監控端點的路徑。

targets 指定應用的IP端口,這里使用了IP,沒有使用localhost,因為 Prometheus 是容器運行的,如果使用 localhost 就會訪問容器內部。

配置不是直接在容器內部修改,可以把容器內部的配置文件拷貝出來一份,修改后,重啟啟動容器,掛載本地修改過的配置文件。

拷貝容器中的配置文件:

$ docker cp [容器ID]:/etc/prometheus/prometheus.yml .

修改配置文件,添加配置,最終的內容:

# my global config
global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.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: 'springboot_app'
    scrape_interval: 5s
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['192.168.31.6:8080']
        "labels": {
            "instance": "springboot2-A",
            "service": "springboot2-A-service"
        }

停掉之前的容器,重新啟動:

$ docker run --name prometheus -d \
    -p 9090:9090 \
    -v [PATH]/prometheus.yml:/etc/prometheus/prometheus.yml \
    prom/prometheus

訪問監控列表頁 http://localhost:9090/targets 就可以看到我們的應用了:

點擊端點鏈接,可以看到監控數據,例如:

進入查詢控制台頁面 http://localhost:9090/graph,可以查詢一個指標,例如 http_server_requests_seconds_sum,效果:

4. 部署 Grafana

docker方式運行:

$ docker run -d \
    -p 3000:3000 \
    --name=grafana \
    grafana/grafana

啟動后,訪問:http://localhost:3000,默認用戶名密碼 admin/admin

5. 添加 Prometheus 數據源

6. 展示應用的 JVM 信息

Grafana 中已經有現成的 JVM 儀表盤,我們直接導入使用即可。

這個儀表盤的編號為 4701

至此,Prometheus + Grafana + Springboot 的整體流程已經跑通了。

但是,這些指標都是底層通用指標,在業務層面一定會有個性需求,下面我們自己定義一些監控指標。

7. 自定義監控指標

需求:監控所有接口的請求次數。

應用中添加依賴:

		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.9.4</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.9.4</version>
		</dependency>
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>3.2.12</version>
		</dependency>

使用AOP方式對接口請求計數:

package com.example.springboot2demo;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
@Aspect
public class APICounterAop {

    @Pointcut("execution(public * com.example.springboot2demo.*.*(..))")
    public void pointCut() {
    }

    ThreadLocal<Long> startTime = new ThreadLocal<>();

    @Autowired
    MeterRegistry registry;
    private Counter counter;

    @PostConstruct
    private void init() {
        counter = registry.counter("requests_total", "status", "success");
    }

    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        System.out.println("do before");
        counter.increment(); //請求計數
    }

    @AfterReturning(returning = "returnVal", pointcut = "pointCut()")
    public void doAfterReturning(Object returnVal) {
        System.out.println("do after");
    }
}

創建一個測試接口:

package com.example.springboot2demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }
}

重啟應用,多訪問幾次測試接口,然后查看 Prometheus 中的應用監控端點頁面,就可以看到監控結果:

然后,我們把這個指標在 Grafana 中顯示出來。

8. 動態變更監控目標

上面 Prometheus 配置文件中定義的監控目標使用的是靜態方式,改配置文件后需要重啟。

如果服務變更了,或者增加服務了,經常重啟 Prometheus 肯定不合適。

Prometheus 提供了動態加載的方式,把服務信息放到一個單獨的文件中,Prometheus 配置中指定這個外部文件,內容變化后,Prometheus 就會自動重新加載。

服務信息配置文件例如:

[
    {
        "targets": [
            "192.168.31.6:8080"
        ],
        "labels": {
            "instance": "springboot2-A",
            "service": "springboot2-A-service"
        }
    }
]

Prometheus 配置文件中的寫法:

...
  - job_name: 'springboot_app'
    scrape_interval: 5s
    metrics_path: '/actuator/prometheus'
    file_sd_configs:
    - files:
      - /home/*.json
      refresh_interval: 1m

啟動 Prometheus 容器時要掛載這個服務信息配置文件的目錄:

$ docker run --name prometheus -d -p 9090:9090 \
	-v [PATH]/prometheus.yml:/etc/prometheus/prometheus.yml \
	-v [PATH]:/home \
	prom/prometheus

推薦閱讀:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM