【Springboot知识】Springboot进阶-Micrometer指标监控深入解析
文章目录
- Micrometer 核心概念与标准指标详解
- **Micrometer 核心概念与标准指标详解**
- **一、Micrometer 核心概念**
- **二、Micrometer 标准指标**
- **1. JVM 监控指标**
- **2. 系统资源监控**
- **3. HTTP 请求监控**
- **4. 数据库监控**
- **5. 缓存监控**
- **三、配置与自定义指标**
- **1. 启用/禁用特定指标**
- **2. 添加自定义标签**
- **3. 指标命名规则**
- **四、监控数据展示示例(Prometheus)**
- **五、总结**
- springboot结合Micrometer
- **Spring Boot 集成 Micrometer 实现指标监控**
- **一、添加依赖**
- **二、配置监控端点**
- **三、自动采集的指标**
- **四、自定义业务指标**
- **1. 计数器(Counter)统计订单创建次数**
- **2. 计时器(Timer)统计方法耗时**
- **3. 仪表(Gauge)监控队列大小**
- **五、高级配置**
- **1. 全局标签(区分环境/区域)**
- **2. 过滤不需要的指标**
- **3. 自定义指标命名规则**
- **六、验证与可视化**
- **七、总结**
- 自定义一个Micrometer
- **一、自定义 MeterRegistry(监控数据上报)**
- **1. 实现自定义注册中心**
- **2. 注册自定义 Registry 到 Spring 上下文**
- **3. 配置 `application.properties`**
- **二、自定义指标采集逻辑**
- **1. 创建自定义 Meter(例如统计缓存穿透次数)**
- **2. 自定义 MeterFilter(过滤或修改指标)**
- **3. 动态标签(基于请求上下文)**
- **三、验证自定义效果**
- **四、注意事项**
- 关联知识
Micrometer 核心概念与标准指标详解
Micrometer 核心概念与标准指标详解
一、Micrometer 核心概念
Micrometer 是一款 监控指标门面库(类似 SLF4J 在日志领域的作用),为 Java 应用提供统一的监控指标采集接口,支持对接 Prometheus、Datadog、InfluxDB 等主流监控系统。以下是其核心组件:
概念 | 说明 |
---|---|
Meter | 指标的最小单元,表示一个可测量的值(如请求数、响应时间)。 |
MeterRegistry | 管理所有 Meter 的注册中心,负责将指标发布到监控后端(如 Prometheus)。 |
MeterProvider | 创建 Meter 的工厂,支持通过标签(Tags)动态生成指标。 |
Tags | 键值对标签,用于为指标添加维度(如 method=GET , status=200 )。 |
Naming Convention | 指标命名规则(如 snake_case 或 camelCase ),适配不同监控系统的要求。 |
二、Micrometer 标准指标
Micrometer 内置了多种 自动采集的指标,涵盖 JVM、系统资源、HTTP 请求等关键领域。
1. JVM 监控指标
指标名称 | 类型 | 说明 |
---|---|---|
jvm.memory.used | Gauge | JVM 内存使用量(单位:字节) |
jvm.memory.committed | Gauge | JVM 已提交内存(包括未使用的预分配内存) |
jvm.threads.live | Gauge | 当前存活线程数 |
jvm.gc.pause | Timer | GC 暂停时间统计(次数、总耗时、最大耗时) |
jvm.classes.loaded | Gauge | 已加载的类数量 |
示例配置(自动启用):
management.metrics.enable.jvm=true
2. 系统资源监控
指标名称 | 类型 | 说明 |
---|---|---|
system.cpu.usage | Gauge | 系统 CPU 使用率(0~1) |
process.cpu.usage | Gauge | 当前进程 CPU 使用率 |
process.files.open | Gauge | 进程打开的文件句柄数 |
process.uptime | Gauge | 进程运行时间(单位:秒) |
示例配置:
management.metrics.enable.process=true
management.metrics.enable.system=true
3. HTTP 请求监控
Spring Boot 自动为 Web 应用(如 Spring MVC)生成 HTTP 指标:
指标名称 | 类型 | 说明 |
---|---|---|
http.server.requests | Timer | HTTP 请求耗时统计(次数、延迟、状态码等) |
http.client.requests | Timer | HTTP 客户端请求耗时(如 RestTemplate 调用) |
标签示例:
• method
: HTTP 方法(GET/POST 等)
• uri
: 请求路径(如 /api/users
)
• status
: HTTP 状态码(200/404/500 等)
启用配置:
management.metrics.enable.http=true
4. 数据库监控
集成 HikariCP、Tomcat JDBC 等连接池时自动生成:
指标名称 | 类型 | 说明 |
---|---|---|
jdbc.connections.active | Gauge | 活跃数据库连接数 |
jdbc.connections.idle | Gauge | 空闲数据库连接数 |
jdbc.connections.max | Gauge | 最大允许连接数 |
标签示例:
• pool
: 连接池名称(如 HikariPool-1
)
5. 缓存监控
支持 Caffeine、EhCache 等缓存框架:
指标名称 | 类型 | 说明 |
---|---|---|
cache.gets | Counter | 缓存查询次数(命中 + 未命中) |
cache.hits | Counter | 缓存命中次数 |
cache.size | Gauge | 缓存当前条目数 |
标签示例:
• name
: 缓存名称(如 usersCache
)
• result
: 结果类型(hit/miss)
三、配置与自定义指标
1. 启用/禁用特定指标
# 禁用 JVM 内存指标
management.metrics.enable.jvm.memory.used=false
2. 添加自定义标签
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config()
.commonTags("region", "us-east-1", "env", "prod");
}
3. 指标命名规则
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsNaming() {
return registry -> registry.config()
.namingConvention(NamingConvention.snakeCase);
}
四、监控数据展示示例(Prometheus)
从 /actuator/prometheus
端点获取的数据示例:
# HTTP 请求指标
http_server_requests_seconds_count{method="GET",uri="/api/users",status="200"} 42
http_server_requests_seconds_sum{method="GET",uri="/api/users",status="200"} 12.7
# JVM 内存使用
jvm_memory_used_bytes{area="heap",id="PS Eden Space"} 256000000
五、总结
• 核心价值:
Micrometer 通过统一 API 屏蔽监控后端差异,开发者只需关注业务指标采集。
• 标准指标覆盖场景:
JVM、HTTP、数据库、缓存等关键组件均已内置监控,开箱即用。
• 扩展性:
通过自定义 MeterRegistry
和 Meter
可集成私有监控系统。
springboot结合Micrometer
Spring Boot 集成 Micrometer 实现指标监控
Micrometer 是 Spring Boot 的官方监控工具库,通过 Actuator 模块提供开箱即用的指标采集能力。以下是完整的集成与自定义指标实现步骤:
一、添加依赖
在 pom.xml
中添加核心依赖(以 Prometheus 为例):
<!-- Spring Boot Actuator(暴露监控端点) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Micrometer 核心库 -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<!-- 对接 Prometheus 的 Registry -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
二、配置监控端点
在 application.properties
中启用端点并配置 Prometheus:
# 暴露所有 Actuator 端点(生产环境建议按需暴露)
management.endpoints.web.exposure.include=*
# 配置应用名称(作为指标前缀)
management.metrics.tags.application=my-springboot-app
# 配置 Prometheus 抓取间隔
management.metrics.export.prometheus.step=30s
三、自动采集的指标
Spring Boot 会 自动生成以下指标(无需额外代码):
指标类型 | 示例指标 | 说明 |
---|---|---|
JVM 监控 | jvm_memory_used_bytes | JVM 内存使用量 |
HTTP 请求 | http_server_requests_seconds | HTTP 接口耗时统计 |
数据库连接池 | jdbc_connections_active | 活跃数据库连接数 |
系统资源 | system_cpu_usage | 系统 CPU 使用率 |
访问 http://localhost:8080/actuator/prometheus
查看原始指标数据。
四、自定义业务指标
1. 计数器(Counter)统计订单创建次数
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;
@Component
public class OrderMetrics {
private final Counter orderCreatedCounter;
public OrderMetrics(MeterRegistry registry) {
// 初始化计数器(带业务标签)
orderCreatedCounter = Counter.builder("order.created")
.description("订单创建次数统计")
.tag("type", "online") // 静态标签
.register(registry);
}
public void incrementOrderCreated(String userId) {
// 动态添加标签(例如用户ID)
orderCreatedCounter
.bind(Tags.of("user", userId))
.increment();
}
}
在业务代码中调用:
@Autowired
private OrderMetrics orderMetrics;
public void createOrder(Order order) {
// 业务逻辑...
orderMetrics.incrementOrderCreated(order.getUserId());
}
2. 计时器(Timer)统计方法耗时
使用 @Timed
注解自动记录方法耗时:
import io.micrometer.core.annotation.Timed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/users")
@Timed(value = "user.fetch.all", description = "查询所有用户的耗时")
public List<User> getAllUsers() {
// 业务逻辑...
return userService.findAll();
}
}
或手动记录代码块耗时:
import io.micrometer.core.instrument.Timer;
public class PaymentService {
private final Timer paymentTimer;
public PaymentService(MeterRegistry registry) {
paymentTimer = Timer.builder("payment.process.time")
.description("支付处理耗时")
.register(registry);
}
public void processPayment() {
Timer.Sample sample = Timer.start(registry);
try {
// 支付业务逻辑...
} finally {
sample.stop(paymentTimer);
}
}
}
3. 仪表(Gauge)监控队列大小
import io.micrometer.core.instrument.Gauge;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.PostConstruct;
import java.util.Queue;
@Component
public class MessageQueueMetrics {
private final Queue<Message> messageQueue;
private final AtomicInteger queueSize = new AtomicInteger(0);
public MessageQueueMetrics(Queue<Message> messageQueue, MeterRegistry registry) {
this.messageQueue = messageQueue;
// 注册 Gauge(动态获取队列大小)
Gauge.builder("message.queue.size", queueSize, AtomicInteger::get)
.description("消息队列当前大小")
.register(registry);
}
@Scheduled(fixedRate = 5000)
public void updateQueueSize() {
queueSize.set(messageQueue.size());
}
}
五、高级配置
1. 全局标签(区分环境/区域)
@Bean
public MeterRegistryCustomizer<MeterRegistry> globalTags() {
return registry -> registry.config()
.commonTags("env", "prod", "region", "us-east-1");
}
2. 过滤不需要的指标
@Bean
public MeterFilter excludeJvmThreadMetrics() {
return MeterFilter.deny(id -> id.getName().startsWith("jvm.threads"));
}
3. 自定义指标命名规则
@Bean
public MeterRegistryCustomizer<MeterRegistry> namingConvention() {
return registry -> registry.config()
.namingConvention(NamingConvention.snakeCase);
}
六、验证与可视化
-
查看原始指标:
访问http://localhost:8080/actuator/prometheus
,搜索自定义指标(如order_created_total
)。 -
对接 Prometheus + Grafana:
• 在prometheus.yml
中添加 Spring Boot 应用的抓取配置:scrape_configs: - job_name: 'spring-boot-app' metrics_path: '/actuator/prometheus' static_configs: - targets: ['localhost:8080']
• 在 Grafana 中导入 Spring Boot 仪表板(如 ID 4701)。
七、总结
• 开箱即用:Spring Boot 自动采集 JVM、HTTP、DB 等核心指标。
• 灵活扩展:通过 Counter
、Timer
、Gauge
轻松添加业务指标。
• 生产就绪:结合 Prometheus + Grafana 实现监控告警与可视化。
自定义一个Micrometer
在 Spring Boot 中自定义 Micrometer 的核心是创建 自定义的 MeterRegistry
或 自定义指标采集逻辑。以下是详细步骤和代码示例:
一、自定义 MeterRegistry(监控数据上报)
1. 实现自定义注册中心
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.core.instrument.step.StepMeterRegistry;
import java.util.concurrent.TimeUnit;
public class CustomMeterRegistry extends StepMeterRegistry {
private final CustomRegistryConfig config;
public CustomMeterRegistry(CustomRegistryConfig config, Clock clock) {
super(config, clock);
this.config = config;
// 设置命名规则(如转驼峰为下划线)
config().namingConvention(NamingConvention.snakeCase);
start(); // 启动后台线程
}
@Override
protected void publish() {
// 自定义上报逻辑(例如将指标发送到 Kafka 或 HTTP API)
getMeters().forEach(meter -> {
meter.match(
gauge -> log.info("Gauge: {}={}", gauge.getId(), gauge.value()),
counter -> log.info("Counter: {}={}", counter.getId(), counter.count()),
timer -> log.info("Timer: {}={}s", timer.getId(), timer.totalTime(TimeUnit.SECONDS)),
// 其他 Meter 类型处理...
meter -> {}
);
});
}
@Override
protected TimeUnit getBaseTimeUnit() {
return TimeUnit.MILLISECONDS; // 定义时间单位
}
// 自定义配置类(继承 StepRegistryConfig)
public static class CustomRegistryConfig extends StepRegistryConfig {
public CustomRegistryConfig() {
super("custom"); // 配置前缀为 "custom"
}
@Override
public String prefix() {
return "custom.metrics";
}
}
}
2. 注册自定义 Registry 到 Spring 上下文
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MetricsConfig {
@Bean
public CustomMeterRegistry customMeterRegistry() {
CustomMeterRegistry.CustomRegistryConfig config = new CustomMeterRegistry.CustomRegistryConfig();
return new CustomMeterRegistry(config, Clock.SYSTEM);
}
}
3. 配置 application.properties
# 自定义 Registry 参数
custom.metrics.step=30s # 数据上报间隔
custom.metrics.enabled=true
二、自定义指标采集逻辑
1. 创建自定义 Meter(例如统计缓存穿透次数)
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;
@Component
public class CacheMetrics {
private final Counter cachePenetrationCounter;
public CacheMetrics(MeterRegistry registry) {
// 定义指标名称、描述、标签
cachePenetrationCounter = Counter.builder("cache.penetration")
.description("缓存穿透次数统计")
.tag("cache", "userCache")
.register(registry);
}
public void recordPenetration() {
cachePenetrationCounter.increment();
}
}
在业务代码中调用:
@Autowired
private CacheMetrics cacheMetrics;
public User getUserById(Long id) {
User user = cache.get(id);
if (user == null) {
cacheMetrics.recordPenetration(); // 记录穿透事件
user = database.load(id);
}
return user;
}
2. 自定义 MeterFilter(过滤或修改指标)
import io.micrometer.core.instrument.config.MeterFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public MeterFilter renameTagFilter() {
// 将标签名 "method" 改为 "http_method"
return MeterFilter.renameTag("http.server.requests", "method", "http_method");
}
@Bean
public MeterFilter denyTestEndpoints() {
// 禁止统计 "/actuator" 端点的请求
return MeterFilter.deny(id -> id.getName().startsWith("http.server.requests")
&& id.getTag("uri") != null
&& id.getTag("uri").startsWith("/actuator"));
}
}
3. 动态标签(基于请求上下文)
使用 MeterFilter
添加动态标签(例如根据请求头添加租户 ID):
import org.springframework.web.servlet.HandlerInterceptor;
public class TenantTagInterceptor implements HandlerInterceptor {
private final MeterRegistry registry;
public TenantTagInterceptor(MeterRegistry registry) {
this.registry = registry;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String tenantId = request.getHeader("X-Tenant-ID");
if (tenantId != null) {
// 为所有指标添加租户标签
registry.config().commonTags("tenant", tenantId);
}
return true;
}
}
注册拦截器:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private MeterRegistry registry;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TenantTagInterceptor(this.registry));
}
}
三、验证自定义效果
-
查看原始指标数据
访问/actuator/prometheus
,搜索自定义指标(如cache_penetration_total
)。 -
日志验证
如果自定义的CustomMeterRegistry
实现了日志输出,检查日志中是否打印指标数据。 -
集成测试
编写测试用例验证指标是否被正确记录:
@SpringBootTest
public class CacheMetricsTest {
@Autowired
private CacheMetrics cacheMetrics;
@Autowired
private MeterRegistry registry;
@Test
public void testCachePenetration() {
cacheMetrics.recordPenetration();
Counter counter = registry.find("cache.penetration").counter();
assertThat(counter.count()).isEqualTo(1.0);
}
}
四、注意事项
-
性能影响
避免在publish()
方法中执行阻塞操作(如同步 HTTP 请求),使用异步或批处理上报。 -
标签基数爆炸
动态标签(如用户 ID)可能导致指标数量激增,建议仅用于低基数字段(如租户、区域)。 -
注册中心冲突
如果同时使用多个MeterRegistry
(如 Prometheus 和自定义),确保指标不会重复上报。 -
命名规范
遵循监控系统的命名规则(如 Prometheus 要求小写和下划线)。
通过以上步骤,你可以在 Spring Boot 中灵活自定义 Micrometer,适配私有监控系统或实现特定业务指标的采集。
关联知识
【Springboot知识】Springboot进阶-Actuator深入理解
【Micrometer官网地址】