Spring Boot 工程集成 Micrometer

pom.xml

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

application.properties

server.port=8088
spring.application.name=springboot2-prometheus
management.endpoints.web.exposure.include=*
management.metrics.tags.application=${spring.application.name}

启动类

@SpringBootApplication
public class Springboot2PrometheusApplication {

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

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

启动服务,浏览器访问 http://127.0.0.1:8088/actuator/prometheus 就可以看到应用的 一系列不同类型 metrics 信息,例如 http_server_requests_seconds summary、jvm_memory_used_bytes gauge、jvm_gc_memory_promoted_bytes_total counter 等等。

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_查询语句

配置 Prometheus 监控应用指标

$ vim prommetheus.yml

......
- job_name: 'application'
    scrape_interval: 5s
    metrics_path: '/actuator/prometheus'
    file_sd_configs:
      - files: ['/usr/local/prometheus/groups/applicationgroups/*.json']

$ vim groups/applicationgroups/application.json

[
    {
        "targets": [
            "192.168.1.124:8088"
        ],
        "labels": {
            "instance": "springboot2-prometheus",
            "service": "springboot2-prometheus-service"
        }
    }
]

这里 192.168.1.124:8088 就是上边本地启动的服务地址,也就是 Prometheus 要监控的服务地址,同时添加一些与应用相关的标签,方便后期执行 PromSQL 查询语句区分。最后重启 Prometheus 服务,查看 Prometheus UI 界面确认 Target 是否添加成功。

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_prometheus_02

配置 Grafana Dashboard 展示监控项

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

启动完毕后,浏览器访问 http://192.168.1.121:3000 即可,首次登录使用 admin:admin 默认账户密码登录并修改密码。登录完毕,需要添加数据源,这里我们要添加的就是上边 Prometheus 数据源,配置如下图:

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_后端_03

配置完毕,接下来需要导入对应的监控 JVM 的 Dashboard 模板,模板编号为 4701

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_prometheus_04

导入完毕后,就可以看到 JVM (Micrometer) 各种类型指标监控图形化以后的页面。

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_prometheus_05

监控某几个 API 请求次数

@RestController
@RequestMapping("/v1")
public class IndexController {

    @Autowired
    MeterRegistry registry;

    private Counter counter_core;
    private Counter counter_index;

    @PostConstruct
    private void init(){
        counter_core = registry.counter("app_requests_method_count", "method", "IndexController.core");
        counter_index = registry.counter("app_requests_method_count", "method", "IndexController.index");
    }

    @RequestMapping(value = "/index")
    public Object index(){
        try{
            counter_index.increment();
        } catch (Exception e) {
            return e;
        }
        return counter_index.count() + " index of springboot2-prometheus.";
    }

    @RequestMapping(value = "/core")
    public Object coreUrl(){
        try{
            counter_core.increment();
        } catch (Exception e) {
            return e;
        }
        return counter_core.count() + " coreUrl Monitor by Prometheus.";
    }
}

说明一下,这里是一个简单的 RestController 接口,使用了 Counter 计量器来统计访问 /v1/index 及 /v1/core 接口访问量。因为访问数会持续的增加,所以这里使用 Counter 比较合适。启动服务,我们来分别访问一下这两个接口,为了更好的配合下边演示,可以多访问几次。

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_spring_06

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_prometheus_07

服务可以正常访问,并且访问了 6 次 /v1/index,访问了 10 次 /v1/core。接下来,我们可以到 Prometheus UI 界面上使用 PromSQL 查询自定义的监控信息了。分别添加 Graph 并执行如下查询语句,查询结果如下:

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_prometheus_08

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_后端_09

可以看到正确统计出来这两个接口请求的访问数,这里解释一下查询语句:

app_requests_method_count_total{application="springboot2-prometheus", instance="springboot2-prometheus", method="IndexController.core"}

这里的app_requests_method_count_total 为上边代码中设置的 Counter 名称。
application 为初始化 registry 时设置的通用标签,标注应用名称,这样做好处就是可以根据应用名称区分不同的应用。
instance 为 <local_dir>/groups/applicationgroups/application.json 中配置的 instance 实例名称,用来区分应用实例。
method 为上边代码中设置的 Counter 标签名称,可以用来区分不同的方法,这样就不用为每一个方法设置一个 Counter 了。
接下来,我们在 Grafana Dashboard 上添加一个新的 Panel 并添加 Query 查询,最后图形化展示出来。首先添加一个 Panel 并命名为 自定义监控指标,然后点击 Add Query 增加一个新的 Query 查询,查询语句为上边的 PromSQL 语句,不过这里为了更好的扩展性,我们可以将 application 及 instance 两个参数赋值为变量,而这些变量可以直接从 Prometheus 上传递过来,最终的查询语句为

app_requests_method_count_total{application="$application", instance="$instance", method="IndexController.core"}

最后修改 Title 为 实时访问量 /v1/core,保存一下,返回首页就可以看到刚添加的 Dashboard 了,是不是很直观。

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_prometheus_10

监控所有 API 请求次数

监控请求次数可以继续使用 Counter 计数器,整个应用所有请求,我们自然而然的想到了 Spring AOP,通过切面注入可以做到统计所有请求记录,添加依赖如下:

...
	<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>
@Component
@Aspect
public class AspectAop {

    @Autowired
    MeterRegistry registry;

    private Counter counter_total;

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

    @Pointcut("execution(public * com.promethues.demo.controller.*.*(..))")
    private void pointCut(){}

    @PostConstruct
    public void init(){
        counter_total = registry.counter("app_requests_count", "v1", "core");
    }

    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint)throws Throwable {
        startTime.set(System.currentTimeMillis());
        counter_total.increment();
    }

    @AfterReturning(returning = "returnVal", pointcut = "pointCut()")
    public void doAftereReturning(Object returnVal){
        System.out.println("请求执行时间:" + (System.currentTimeMillis() - startTime.get()));
    }
}

我们创建了一个名称为 app_requests_count 的 Counter,所有请求过来都会执行 counter_total.increment(); 操作,从而实现统计所有请求总数。重启服务,访问多次不同的接口,然后在 Prometheus UI 界面执行 PromSQL 查询,查询语句为

app_requests_count_total{application="springboot2-prometheus", instance="springboot2-prometheus", v1="core"}

查询结果如下:

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_prometheus_11

可以看到,能够正确统计出来所有的请求数量,现在,我们可以在 Grafana 上之前的面板上增加一个新的 Query 并图形化显示出来了,Query 语句为:

app_requests_count_total{application="$application", instance="$instance",v1="core"}

添加完成后,展示效果如下:

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_spring_12

监控实时在线人数

@RestController
@RequestMapping("/v1")
public class IndexController {

    @Autowired
    MeterRegistry registry;

    private Counter counter_core;
    private Counter counter_index;
    private AtomicInteger app_online_count;

    @PostConstruct
    private void init(){
        counter_core = registry.counter("app_requests_method_count", "method", "IndexController.core");
        counter_index = registry.counter("app_requests_method_count", "method", "IndexController.index");
        app_online_count = registry.gauge("app_online_count", new AtomicInteger(0));
    }

    @RequestMapping(value = "/index")
    public Object index(){
        try{
            counter_index.increment();
        } catch (Exception e) {
            return e;
        }
        return counter_index.count() + " index of springboot2-prometheus.";
    }

    @RequestMapping(value = "/core")
    public Object coreUrl(){
        try{
            counter_core.increment();
        } catch (Exception e) {
            return e;
        }
        return counter_core.count() + " coreUrl Monitor by Prometheus.";
    }
    
    @RequestMapping(value = "/online")
    public Object onlineCount(){
        int people = 0;
        try {
            people = new Random().nextInt(2000);
            app_online_count.set(people);
        } catch (Exception e){
            return e;
        }
        return "current online people: " + people;
    }
}

重启服务,访问一下 /v1/online 接口,得到一个 2000 以内的随机数作为实时在线人数,浏览器访问一下,得到结果如下:

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_spring_13

我们在 Prometheus UI 界面执行一下 PromeSQL 查询语句

app_online_count{application="springboot2-prometheus", instance="springboot2-prometheus"}

同样能够对应获取到实时数据。

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_后端_14

继续在 Grafana 上之前的面板上增加一个新的 Query 并图形化显示出来,Query 语句为: app_online_count{application="$application", instance="$instance"}, 添加完成后,展示效果如下:

Spring Boot 集成 micrometer prometheus 代码示例: 监控某几个 API 请求次数和所有 API 请求次数、监控实时在线人数_prometheus_15