java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot Prometheus监控

SpringBoot Admin与Prometheus集成监控

作者:CarlowZJ

本文深入探讨Spring Boot Admin与Prometheus的集成监控方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

摘要

本文深入探讨Spring Boot Admin与Prometheus的集成监控方案,包括指标收集、数据导出、可视化展示等关键技术点。通过详细的技术解析和实践示例,帮助开发者构建完整的微服务监控体系。

1. 引言

Prometheus作为开源的系统监控和报警工具包,已经成为云原生监控的标准。Spring Boot Admin结合Prometheus可以提供更强大的监控能力。本文将详细介绍如何实现两者的集成。

2. Prometheus基础

2.1 Prometheus架构

Prometheus生态系统包含以下组件:

2.2 数据模型

Prometheus使用时间序列数据模型,每个时间序列由指标名称和键值对标签标识。

3. 集成配置

3.1 依赖配置

<dependencies>
    <!-- Spring Boot Admin Server -->
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-server</artifactId>
    </dependency>
    
    <!-- Spring Boot Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
    <!-- Micrometer Prometheus Registry -->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>
    
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

3.2 应用配置

# application.yml
server:
  port: 8022

spring:
  application:
    name: admin-server-prometheus

# Actuator配置
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
      base-path: /actuator
  endpoint:
    health:
      show-details: always
    prometheus:
      enabled: true
  metrics:
    export:
      prometheus:
        enabled: true
    distribution:
      percentiles-histogram:
        all: true
      sla:
        http.server.requests: 10ms, 50ms, 100ms, 200ms, 500ms, 1000ms

# Spring Boot Admin配置
boot:
  admin:
    server:
      ui:
        title: 'Prometheus集成监控平台'
        brand: '<img src="assets/img/icon-spring-boot-admin.svg"><span>Prometheus集成监控平台</span>'

info:
  app:
    name: ${spring.application.name}
    version: ${project.version}
    description: Spring Boot Admin与Prometheus集成示例

4. 指标收集与暴露

4.1 自定义指标收集器

package com.springboot.admin.prometheus;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.springframework.stereotype.Component;

@Component
public class CustomMetricsCollector implements MeterBinder {
    
    private Counter requestCounter;
    private Counter errorCounter;
    
    @Override
    public void bindTo(MeterRegistry registry) {
        // 请求计数器
        requestCounter = Counter.builder("http_requests_total")
            .description("Total number of HTTP requests")
            .register(registry);
            
        // 错误计数器
        errorCounter = Counter.builder("http_errors_total")
            .description("Total number of HTTP errors")
            .register(registry);
            
        // 系统指标
        Gauge.builder("system_cpu_usage")
            .description("System CPU usage")
            .register(registry, this, obj -> getSystemCpuUsage());
            
        Gauge.builder("system_memory_usage")
            .description("System memory usage")
            .register(registry, this, obj -> getSystemMemoryUsage());
    }
    
    public void incrementRequest() {
        if (requestCounter != null) {
            requestCounter.increment();
        }
    }
    
    public void incrementError() {
        if (errorCounter != null) {
            errorCounter.increment();
        }
    }
    
    private double getSystemCpuUsage() {
        // 获取系统CPU使用率
        return Math.random() * 100; // 模拟数据
    }
    
    private double getSystemMemoryUsage() {
        // 获取系统内存使用率
        long totalMemory = Runtime.getRuntime().totalMemory();
        long freeMemory = Runtime.getRuntime().freeMemory();
        return (double) (totalMemory - freeMemory) / totalMemory * 100;
    }
}

4.2 业务指标收集

package com.springboot.admin.prometheus;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Timer;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class BusinessMetricsService {
    
    private final MeterRegistry meterRegistry;
    private final Timer businessOperationTimer;
    
    public BusinessMetricsService(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        
        // 业务操作计时器
        this.businessOperationTimer = Timer.builder("business.operation.duration")
            .description("Business operation duration")
            .register(meterRegistry);
    }
    
    public <T> T recordBusinessOperation(String operationName, java.util.function.Supplier<T> operation) {
        return businessOperationTimer
            .tag("operation", operationName)
            .recordCallable(operation::get);
    }
    
    public void recordBusinessEvent(String eventType, String service) {
        meterRegistry.counter("business.events.total", 
            Tag.of("type", eventType),
            Tag.of("service", service))
            .increment();
    }
    
    public void recordBusinessGauge(String name, double value, String service) {
        meterRegistry.gauge("business." + name, 
            Tag.of("service", service), 
            value);
    }
}

5. Prometheus配置

5.1 Prometheus配置文件

# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alert_rules.yml"

scrape_configs:
  - job_name: 'admin-server'
    static_configs:
      - targets: ['localhost:8022']
    metrics_path: '/actuator/prometheus'
    scrape_interval: 10s
    scrape_timeout: 5s
    honor_labels: true
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance

  - job_name: 'microservices'
    metrics_path: '/actuator/prometheus'
    scrape_interval: 10s
    scrape_timeout: 5s
    static_configs:
      - targets: ['service1:8080', 'service2:8081', 'service3:8082']
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['alertmanager:9093']

5.2 告警规则配置

# alert_rules.yml
groups:
  - name: admin_server_alerts
    rules:
      - alert: AdminServerDown
        expr: up{job="admin-server"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Admin Server is down"
          description: "Admin Server {{ $labels.instance }} has been down for more than 1 minute."

      - alert: HighCpuUsage
        expr: system_cpu_usage > 80
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "High CPU usage on {{ $labels.instance }}"
          description: "CPU usage is above 80% on instance {{ $labels.instance }}."

      - alert: HighMemoryUsage
        expr: system_memory_usage > 85
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "High memory usage on {{ $labels.instance }}"
          description: "Memory usage is above 85% on instance {{ $labels.instance }}."

      - alert: HighErrorRate
        expr: rate(http_errors_total[5m]) > 10
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "High error rate on {{ $labels.instance }}"
          description: "Error rate is above 10 requests per minute on instance {{ $labels.instance }}."

6. 数据导出与格式化

6.1 自定义指标格式化

package com.springboot.admin.prometheus;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import org.springframework.stereotype.Component;

@Component
public class PrometheusCustomFormatter {
    
    public void customizePrometheusRegistry(PrometheusMeterRegistry registry) {
        // 自定义指标格式化
        registry.config()
            .meterFilter(new io.micrometer.core.instrument.config.MeterFilter() {
                @Override
                public io.micrometer.core.instrument.Meter.Id map(io.micrometer.core.instrument.Meter.Id id) {
                    // 添加自定义标签
                    if (id.getName().startsWith("http.")) {
                        return id.withTags(io.micrometer.core.instrument.Tag.of("application", "admin-server"));
                    }
                    return id;
                }
            });
    }
}

6.2 指标数据处理

package com.springboot.admin.prometheus;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

@Component
public class MetricsProcessor {
    
    private final MeterRegistry meterRegistry;
    private final ConcurrentHashMap<String, AtomicLong> customCounters = new ConcurrentHashMap<>();
    
    public MetricsProcessor(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    public void incrementCustomCounter(String name, String... tags) {
        String key = buildKey(name, tags);
        AtomicLong counter = customCounters.computeIfAbsent(key, k -> new AtomicLong(0));
        long value = counter.incrementAndGet();
        
        // 同步到Prometheus
        meterRegistry.counter("custom." + name, 
            buildTags(tags))
            .increment();
    }
    
    public void recordCustomGauge(String name, double value, String... tags) {
        meterRegistry.gauge("custom." + name, 
            java.util.Arrays.asList(buildTags(tags)), 
            value);
    }
    
    private String buildKey(String name, String... tags) {
        StringBuilder key = new StringBuilder(name);
        for (String tag : tags) {
            key.append(".").append(tag);
        }
        return key.toString();
    }
    
    private Iterable<Tag> buildTags(String... tags) {
        java.util.List<Tag> tagList = new java.util.ArrayList<>();
        for (int i = 0; i < tags.length; i += 2) {
            if (i + 1 < tags.length) {
                tagList.add(Tag.of(tags[i], tags[i + 1]));
            }
        }
        return tagList;
    }
}

7. 监控面板集成

7.1 Grafana配置

{
  "dashboard": {
    "id": null,
    "title": "Admin Server Dashboard",
    "tags": ["admin", "spring-boot", "prometheus"],
    "timezone": "browser",
    "panels": [
      {
        "id": 1,
        "title": "HTTP Requests",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_requests_total[1m])",
            "legendFormat": "Requests per second"
          }
        ]
      },
      {
        "id": 2,
        "title": "System CPU Usage",
        "type": "singlestat",
        "targets": [
          {
            "expr": "system_cpu_usage",
            "legendFormat": "CPU Usage"
          }
        ]
      },
      {
        "id": 3,
        "title": "System Memory Usage",
        "type": "graph",
        "targets": [
          {
            "expr": "system_memory_usage",
            "legendFormat": "Memory Usage"
          }
        ]
      }
    ]
  }
}

7.2 监控数据API

package com.springboot.admin.api;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/metrics")
public class MetricsApiController {
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    @Autowired
    private PrometheusMeterRegistry prometheusRegistry;
    
    @GetMapping("/prometheus")
    public ResponseEntity<String> getPrometheusMetrics() {
        return ResponseEntity.ok(prometheusRegistry.scrape());
    }
    
    @GetMapping("/summary")
    public ResponseEntity<MetricsSummary> getMetricsSummary() {
        MetricsSummary summary = new MetricsSummary();
        
        // 获取各种指标的摘要信息
        summary.setTotalMeters(meterRegistry.getMeters().size());
        summary.setGauges(meterRegistry.find("gauge").meters().size());
        summary.setCounters(meterRegistry.find("counter").meters().size());
        summary.setTimers(meterRegistry.find("timer").meters().size());
        
        return ResponseEntity.ok(summary);
    }
    
    public static class MetricsSummary {
        private int totalMeters;
        private int gauges;
        private int counters;
        private int timers;
        
        // getter和setter方法
        public int getTotalMeters() { return totalMeters; }
        public void setTotalMeters(int totalMeters) { this.totalMeters = totalMeters; }
        public int getGauges() { return gauges; }
        public void setGauges(int gauges) { this.gauges = gauges; }
        public int getCounters() { return counters; }
        public void setCounters(int counters) { this.counters = counters; }
        public int getTimers() { return timers; }
        public void setTimers(int timers) { this.timers = timers; }
    }
}

8. 高级功能

8.1 指标过滤与转换

package com.springboot.admin.prometheus;

import io.micrometer.core.instrument.config.MeterFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MetricsFilterConfig {
    
    @Bean
    public MeterFilter metricsFilter() {
        return MeterFilter.maximumAllowableMetrics(1000)
            .andThen(MeterFilter.maximumAllowableTags("http.server.requests", "uri", 100))
            .andThen(MeterFilter.denyUnless(meter -> 
                meter.getName().startsWith("http.") || 
                meter.getName().startsWith("jvm.") ||
                meter.getName().startsWith("system.") ||
                meter.getName().startsWith("tomcat.")
            ));
    }
    
    @Bean
    public MeterFilter namingConventionFilter() {
        return MeterFilter.renameTag("http.server.requests", "method", "httpMethod")
            .andThen(MeterFilter.renameTag("http.server.requests", "uri", "httpUri"));
    }
}

8.2 指标聚合

package com.springboot.admin.prometheus;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Timer;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Component
public class MetricsAggregator {
    
    private final MeterRegistry meterRegistry;
    private final ConcurrentHashMap<String, Timer.Sample> activeOperations = new ConcurrentHashMap<>();
    
    public MetricsAggregator(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    public void startOperation(String operationName, String service) {
        Timer.Sample sample = Timer.start(meterRegistry);
        String key = operationName + ":" + service;
        activeOperations.put(key, sample);
    }
    
    public void endOperation(String operationName, String service) {
        String key = operationName + ":" + service;
        Timer.Sample sample = activeOperations.remove(key);
        if (sample != null) {
            sample.stop(Timer.builder("operation.duration")
                .description("Operation duration")
                .tags(Tag.of("operation", operationName), Tag.of("service", service))
                .register(meterRegistry));
        }
    }
    
    public void recordHistogram(String metricName, double value, String... tags) {
        meterRegistry.timer(metricName, buildTags(tags))
            .record((long) value, TimeUnit.MILLISECONDS);
    }
    
    private Iterable<Tag> buildTags(String... tags) {
        java.util.List<Tag> tagList = new java.util.ArrayList<>();
        for (int i = 0; i < tags.length; i += 2) {
            if (i + 1 < tags.length) {
                tagList.add(Tag.of(tags[i], tags[i + 1]));
            }
        }
        return tagList;
    }
}

9. 部署配置

9.1 Docker配置

# Dockerfile
FROM openjdk:8-jre-alpine

# 创建应用目录
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
WORKDIR /app

# 复制应用文件
COPY --chown=spring:spring target/admin-server-prometheus.jar app.jar

# 暴露端口
EXPOSE 8022

# 启动命令
ENTRYPOINT ["java", "-jar", "app.jar"]

9.2 Docker Compose配置

# docker-compose.yml
version: '3.8'

services:
  admin-server:
    build: .
    container_name: admin-server-prometheus
    ports:
      - "8022:8022"
    environment:
      - SPRING_PROFILES_ACTIVE=prometheus
    networks:
      - monitoring

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
    networks:
      - monitoring

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana-storage:/var/lib/grafana
    networks:
      - monitoring
    depends_on:
      - prometheus

volumes:
  grafana-storage:

networks:
  monitoring:
    driver: bridge

10. 性能优化

10.1 指标收集优化

package com.springboot.admin.optimization;

import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MetricsOptimizationConfig {
    
    @Bean
    public MeterFilter metricsFilter() {
        return MeterFilter.maximumAllowableMetrics(1000)
            .andThen(MeterFilter.denyUnless(meter -> 
                meter.getName().startsWith("http.") || 
                meter.getName().startsWith("jvm.") ||
                meter.getName().startsWith("system.")
            ));
    }
    
    @Bean
    public MeterFilter distributionConfigFilter() {
        return new MeterFilter() {
            @Override
            public DistributionStatisticConfig configure(io.micrometer.core.instrument.Meter.Id id, 
                                                        DistributionStatisticConfig config) {
                if (id.getName().startsWith("http.server.requests")) {
                    return DistributionStatisticConfig.builder()
                        .percentiles(0.5, 0.95, 0.99)
                        .build()
                        .merge(config);
                }
                return config;
            }
        };
    }
}

11. 总结

本文详细介绍了Spring Boot Admin与Prometheus的集成监控方案,包括:

  1. Prometheus基础概念和架构
  2. 集成配置和依赖管理
  3. 指标收集与暴露
  4. Prometheus配置和告警规则
  5. 数据导出与格式化
  6. 监控面板集成
  7. 高级功能实现
  8. 部署配置方案
  9. 性能优化策略

通过合理的集成配置,可以构建一个功能完善的微服务监控体系,为系统运维提供有力支持。

12. 扩展阅读

13. 参考资料

  1. Prometheus GitHub: https://github.com/prometheus/prometheus
  2. Micrometer GitHub: https://github.com/micrometer-metrics/micrometer
  3. Spring Boot Admin GitHub: https://github.com/codecentric/spring-boot-admin

本文为CSDN博主「Spring Cloud技术栈」原创文章,转载请附上原文出处链接和本声明。

到此这篇关于SpringBoot Admin与Prometheus集成监控的文章就介绍到这了,更多相关SpringBoot Prometheus监控内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文