SpringBoot Admin与Prometheus集成监控
作者:CarlowZJ
本文深入探讨Spring Boot Admin与Prometheus的集成监控方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
摘要
本文深入探讨Spring Boot Admin与Prometheus的集成监控方案,包括指标收集、数据导出、可视化展示等关键技术点。通过详细的技术解析和实践示例,帮助开发者构建完整的微服务监控体系。
1. 引言
Prometheus作为开源的系统监控和报警工具包,已经成为云原生监控的标准。Spring Boot Admin结合Prometheus可以提供更强大的监控能力。本文将详细介绍如何实现两者的集成。
2. Prometheus基础
2.1 Prometheus架构
Prometheus生态系统包含以下组件:
- Prometheus Server:收集和存储指标数据
- Client Libraries:用于应用代码中暴露指标
- Pushgateway:支持批处理作业的指标推送
- Alertmanager:处理报警
- 可视化工具:如Grafana
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的集成监控方案,包括:
- Prometheus基础概念和架构
- 集成配置和依赖管理
- 指标收集与暴露
- Prometheus配置和告警规则
- 数据导出与格式化
- 监控面板集成
- 高级功能实现
- 部署配置方案
- 性能优化策略
通过合理的集成配置,可以构建一个功能完善的微服务监控体系,为系统运维提供有力支持。
12. 扩展阅读
13. 参考资料
- Prometheus GitHub: https://github.com/prometheus/prometheus
- Micrometer GitHub: https://github.com/micrometer-metrics/micrometer
- Spring Boot Admin GitHub: https://github.com/codecentric/spring-boot-admin
本文为CSDN博主「Spring Cloud技术栈」原创文章,转载请附上原文出处链接和本声明。
到此这篇关于SpringBoot Admin与Prometheus集成监控的文章就介绍到这了,更多相关SpringBoot Prometheus监控内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
