23

Prometheus + Grafana 监控 SpringBoot

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzA4Nzc4MjI4MQ%3D%3D&%3Bmid=2652403442&%3Bidx=1&%3Bsn=82e0ed75ab58b980edaab5c238e1d7b8
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

整体结构

SpringBoot的 actuator 提供了监控端点。

Prometheus是监控系统,可以从 Springboot 获取监控数据,以时序数据的形式存储,并提供了监控数据的查询服务。

Grafana是专业的 UI 仪表盘系统,支持非常多的数据源,其中就包括 Prometheus,可以便利的从中获取数据,使用仪表盘展示出来。

springboot 2 中引入了 micrometer ,它可以更方便的对接各种监控系统,包括 Prometheus。

eMbaqa3.jpg!web

所以整体的结构就是:

  • 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);

}

}


启动服务。

查看监控端点信息:

mMNZB3R.jpg!web

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 是监控目标列表页:

reAVZzY.jpg!web

http://localhost:9090/graph 是查询控制台,也有简单的图表展示:

r2AjYre.jpg!web

现在还没对接应用,后面对接之后可以看到详细的内容。

3. Prometheus + Springboot应用

监控应用,需要在 Prometheus 配置文件中添加应用的相关信息。

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

查看一下配置文件的默认内容:

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

红框内是我们要关注的部分,按照这个形式添加我们的应用即可。

需要添加的内容为:

- 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 就可以看到我们的应用了:

eAzIBz6.jpg!web

点击端点链接,可以看到监控数据,例如:

QZR3Erb.jpg!web

进入查询控制台页面 http://localhost:9090/graph,可以查询一个指标,例如 http_server_requests_seconds_sum ,效果:

uIna63E.jpg!web

4. 部署 Grafana

docker方式运行:

$ docker run -d \

-p 3000:3000 \

--name=grafana \

grafana/grafana

启动后,访问:http://localhost:3000,默认用户名密码 admin/admin

qUbMr2e.jpg!webuu2IBbf.jpg!web

5. 添加 Prometheus 数据源

Ez2UbaA.jpg!web2IFZnqa.jpg!web3UrEbar.jpg!web

6. 展示应用的 JVM 信息

Grafana 中已经有现成的 JVM 仪表盘,我们直接导入使用即可。

这个仪表盘的编号为 4701

IjUFvqY.jpg!webuErUzeU.jpg!webrM3q6rf.jpg!webUB7nYjj.jpg!web

至此,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 中的应用监控端点页面,就可以看到监控结果:

rA7bqiA.jpg!web

然后,我们把这个指标在 Grafana 中显示出来。

RJF7baz.jpg!webNzeQzyJ.jpg!web

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

推荐阅读:

IVnqyiV.jpg!web

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK