本文目录导读:

我来为您提供一个完整的Spring Boot整合Prometheus的案例,包括监控指标采集、自定义指标和Grafana可视化。
项目依赖配置
Maven依赖 (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
http://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.7.14</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>springboot-prometheus</artifactId>
<version>1.0.0</version>
<properties>
<java.version>1.8</java.version>
<micrometer.version>1.9.5</micrometer.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 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>
<version>${micrometer.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 数据库相关(示例使用) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置文件
application.yml
server:
port: 8080
spring:
application:
name: springboot-prometheus-demo
# H2数据库配置(示例)
h2:
console:
enabled: true
path: /h2-console
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: create-drop
show-sql: true
# Actuator配置
management:
endpoints:
web:
exposure:
include: "*"
exclude: "env,beans"
endpoint:
health:
show-details: always
probes:
enabled: true
metrics:
enabled: true
prometheus:
enabled: true
metrics:
export:
prometheus:
enabled: true
step: 1m
descriptions: true
tags:
application: ${spring.application.name}
enable:
jvm: true
http: true
logback: true
distribution:
percentiles-histogram:
http.server.requests: true
slo:
http.server.requests: 10ms, 50ms, 100ms, 200ms, 500ms, 1s, 5s
percentiles:
http.server.requests: 0.5, 0.9, 0.95, 0.99
主应用类
package com.example.prometheus;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class PrometheusApplication {
public static void main(String[] args) {
SpringApplication.run(PrometheusApplication.class, args);
}
}
自定义指标示例
自定义指标注册器
package com.example.prometheus.metrics;
import io.micrometer.core.instrument.*;
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class CustomMetrics {
private final MeterRegistry meterRegistry;
@Autowired
public CustomMetrics(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
// 计数器示例
public Counter requestCounter;
// 仪表盘示例
public Gauge activeUsers;
// 直方图示例
public Timer requestTimer;
// 摘要示例
public DistributionSummary responseSize;
@PostConstruct
public void init() {
// 创建计数器
requestCounter = Counter.builder("custom_requests_total")
.description("Total number of requests")
.tag("type", "custom")
.register(meterRegistry);
// 创建仪表盘(返回一个函数)
AtomicInteger userCount = new AtomicInteger(0);
activeUsers = Gauge.builder("custom_active_users", userCount,
AtomicInteger::get)
.description("Current number of active users")
.tag("type", "custom")
.register(meterRegistry);
// 创建计时器
requestTimer = Timer.builder("custom_request_duration")
.description("Request processing time")
.publishPercentiles(0.5, 0.9, 0.95, 0.99)
.publishPercentileHistogram()
.sla(Duration.ofMillis(100), Duration.ofMillis(500))
.register(meterRegistry);
// 创建摘要
responseSize = DistributionSummary.builder("custom_response_size")
.description("Response size")
.baseUnit("bytes")
.register(meterRegistry);
}
}
业务服务示例
package com.example.prometheus.service;
import io.micrometer.core.instrument.*;
import io.micrometer.core.instrument.search.Search;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Random;
@Service
@Slf4j
public class OrderService {
@Autowired
private MeterRegistry meterRegistry;
private final Random random = new Random();
// 订单计数器
private final Counter orderCounter;
// 订单处理时间
private final Timer orderTimer;
// 活跃用户数
private final AtomicInteger activeUsers = new AtomicInteger(0);
public OrderService(MeterRegistry registry) {
this.orderCounter = registry.counter("orders_total", "type", "business");
this.orderTimer = registry.timer("order_processing_time");
// 注册仪表盘
registry.gauge("active_users", activeUsers, AtomicInteger::get);
}
/**
* 创建订单
*/
public Order createOrder(OrderRequest request) {
long startTime = System.currentTimeMillis();
try {
// 模拟业务处理
Thread.sleep(random.nextInt(200));
// 创建订单逻辑
Order order = new Order();
order.setId(System.currentTimeMillis());
order.setName(request.getName());
order.setAmount(request.getAmount());
// 增加订单计数
orderCounter.increment();
// 记录订单数量
meterRegistry.counter("orders_created_total", "type", "business", "status", "success")
.increment();
log.info("Order created: {}", order.getId());
return order;
} catch (Exception e) {
meterRegistry.counter("orders_created_total", "type", "business", "status", "failed")
.increment();
log.error("Create order failed", e);
throw new RuntimeException("Create order failed", e);
} finally {
// 记录订单处理时间
long duration = System.currentTimeMillis() - startTime;
orderTimer.record(Duration.ofMillis(duration));
responseSize.record(random.nextInt(1024));
}
}
/**
* 用户登录
*/
public void userLogin() {
activeUsers.incrementAndGet();
meterRegistry.counter("user_logins_total").increment();
}
/**
* 用户登出
*/
public void userLogout() {
if (activeUsers.get() > 0) {
activeUsers.decrementAndGet();
}
}
/**
* 获取活跃用户数
*/
public int getActiveUsers() {
return activeUsers.get();
}
}
控制器示例
package com.example.prometheus.controller;
import com.example.prometheus.metrics.CustomMetrics;
import com.example.prometheus.service.OrderService;
import io.micrometer.core.annotation.Timed;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/api")
@Slf4j
public class ApiController {
@Autowired
private OrderService orderService;
@Autowired
private CustomMetrics customMetrics;
@Autowired
private MeterRegistry meterRegistry;
/**
* 创建订单接口
*/
@PostMapping("/orders")
@Timed(value = "api.orders.create", extraTags = {"version", "v1"})
public Map<String, Object> createOrder(@RequestBody OrderRequest request) {
Map<String, Object> response = new HashMap<>();
try {
// 记录请求计数
customMetrics.requestCounter.increment();
// 计时器
long startTime = System.nanoTime();
// 调用服务
Object order = orderService.createOrder(request);
// 记录请求时间
customMetrics.requestTimer.record(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
response.put("success", true);
response.put("data", order);
} catch (Exception e) {
response.put("success", false);
response.put("error", e.getMessage());
}
// 记录响应大小
customMetrics.responseSize.record(response.toString().length());
return response;
}
/**
* 用户登录
*/
@PostMapping("/login")
public String login(@RequestBody LoginRequest request) {
orderService.userLogin();
return "Login successful";
}
/**
* 用户登出
*/
@PostMapping("/logout")
public String logout() {
orderService.userLogout();
return "Logout successful";
}
/**
* 测试接口
*/
@GetMapping("/test")
public String test() {
// 模拟不同的响应时间
long startTime = System.currentTimeMillis();
try {
int delay = (int) (Math.random() * 300);
Thread.sleep(delay);
} catch (InterruptedException e) {
log.error("Test endpoint interrupted", e);
Thread.currentThread().interrupt();
}
customMetrics.requestCounter.increment();
customMetrics.requestTimer.record(System.currentTimeMillis() - startTime,
TimeUnit.MILLISECONDS);
return "Test endpoint - " + System.currentTimeMillis();
}
/**
* 获取当前指标
*/
@GetMapping("/metrics/status")
public Map<String, Object> getMetricsStatus() {
Map<String, Object> metrics = new HashMap<>();
metrics.put("active_users", orderService.getActiveUsers());
metrics.put("total_requests", customMetrics.requestCounter.count());
return metrics;
}
}
@Data
class OrderRequest {
private String name;
private Double amount;
}
@Data
class LoginRequest {
private String username;
private String password;
}
自定义注解支持
自定义计时器注解
package com.example.prometheus.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Timed {
String name() default "";
String[] extraTags() default {};
}
AOP切面
package com.example.prometheus.aspect;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
public class MetricsAspect {
@Autowired
private MeterRegistry meterRegistry;
@Around("@annotation(timed)")
public Object measureTime(ProceedingJoinPoint joinPoint, Timed timed) throws Throwable {
String methodName = timed.name().isEmpty()
? joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()
: timed.name();
Timer timer = Timer.builder(methodName)
.tags(timed.extraTags())
.publishPercentiles(0.5, 0.9, 0.99)
.register(meterRegistry);
long start = System.nanoTime();
try {
return joinPoint.proceed();
} finally {
timer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
}
}
}
Prometheus配置
prometheus.yml
# Prometheus配置文件
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
labels:
application: 'springboot-prometheus-demo'
environment: 'development'
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
Docker Compose 配置
docker-compose.yml
version: '3.8'
services:
# Spring Boot应用
springboot-app:
build: .
container_name: springboot-prometheus-app
ports:
- "8080:8080"
networks:
- monitoring
# Prometheus
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.enable-lifecycle'
networks:
- monitoring
depends_on:
- springboot-app
# Grafana
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
volumes:
- grafana-data:/var/lib/grafana
networks:
- monitoring
depends_on:
- prometheus
# Node Exporter(可选)
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
ports:
- "9100:9100"
networks:
- monitoring
volumes:
prometheus-data:
grafana-data:
networks:
monitoring:
driver: bridge
Grafana Dashboard配置
dashboard.json (示例)
{
"dashboard": {
"id": null,: "Spring Boot Application Monitoring",
"tags": ["spring-boot", "prometheus"],
"timezone": "browser",
"schemaVersion": 16,
"version": 1,
"refresh": "5s",
"panels": [
{
"title": "HTTP Request Rate",
"type": "graph",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
"targets": [
{
"expr": "rate(http_server_requests_seconds_count[5m])",
"legendFormat": "{{method}} - {{uri}}"
}
]
},
{
"title": "HTTP Request Duration",
"type": "graph",
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0},
"targets": [
{
"expr": "histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket[5m])) by (le))",
"legendFormat": "P95"
},
{
"expr": "histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket[5m])) by (le))",
"legendFormat": "P99"
}
]
},
{
"title": "JVM Memory Usage",
"type": "graph",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 8},
"targets": [
{
"expr": "jvm_memory_used_bytes{jvm_area='heap'}",
"legendFormat": "Heap"
},
{
"expr": "jvm_memory_used_bytes{jvm_area='non-heap'}",
"legendFormat": "Non-Heap"
}
]
},
{
"title": "Custom Metrics - Orders",
"type": "singlestat",
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 16},
"targets": [
{
"expr": "orders_total{type='business'}",
"legendFormat": "Total Orders"
}
],
"valueName": "total"
},
{
"title": "Request Counter",
"type": "singlestat",
"gridPos": {"h": 4, "w": 6, "x": 6, "y": 16},
"targets": [
{
"expr": "custom_requests_total{type='custom'}",
"legendFormat": "Total Requests"
}
],
"valueName": "current"
}
]
}
}
使用说明
测试步骤
-
启动应用
mvn clean package java -jar target/springboot-prometheus-1.0.0.jar
-
访问Prometheus指标
- 打开浏览器访问:
http://localhost:8080/actuator/prometheus - 查看自定义指标:
custom_requests_total、custom_active_users
- 调用接口生成指标
# 创建订单 curl -X POST http://localhost:8080/api/orders \ -H "Content-Type: application/json" \ -d '{"name": "Test Order", "amount": 100.50}'
测试接口
curl http://localhost:8080/api/test
模拟登录登出
curl -X POST http://localhost:8080/api/login \ -H "Content-Type: application/json" \ -d '{"username": "user1", "password": "pass123"}'
curl -X POST http://localhost:8080/api/logout
4. **配置Prometheus**
- 启动Prometheus:`docker-compose up prometheus`
- 访问:`http://localhost:9090/targets`
5. **配置Grafana**
- 启动Grafana:`docker-compose up grafana`
- 访问:`http://localhost:3000`(用户名/密码:admin/admin)
- 添加数据源:Configuration → Data Sources → Add data source → Prometheus
- 设置URL为:`http://prometheus:9090`
## 11. 常见指标说明
| 指标名称 | 类型 | 说明 |
|---------|------|------|
| `http_server_requests_seconds` | Histogram | HTTP请求耗时 |
| `jvm_memory_used_bytes` | Gauge | JVM内存使用 |
| `custom_requests_total` | Counter | 自定义请求总数 |
| `custom_active_users` | Gauge | 活跃用户数 |
| `orders_created_total` | Counter | 创建的订单数 |
| `order_processing_time` | Timer | 订单处理时间 |
这个完整的案例展示了Spring Boot与Prometheus集成的各个方面,包括基础配置、自定义指标、监控数据采集和可视化,您可以根据实际需求进行扩展和调整。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播