SpringBoot + Micrometer + Prometheus + Grafana:自定义业务指标监控

相信很多小伙伴都有过这样的经历:系统上线后运行一段时间,突然出现性能问题或者业务异常,但是却不知道具体原因,只能凭经验猜测,排查起来既费时又费力。特别是当我们需要监控一些关键业务指标(比如订单量、失败率等)时,传统的系统监控往往无法满足需求。

那么,有没有一种方式能让我们轻松地监控自定义的业务指标,并且实时看到这些指标的变化趋势呢?今天我就跟大家分享一套基于SpringBoot + Micrometer + Prometheus + Grafana的完整监控方案。

为什么需要业务指标监控?

先来说说我们面临的挑战。传统的系统监控主要关注CPU、内存、磁盘等基础设施指标,虽然这些很重要,但对于业务层面的问题(比如订单成功率下降、支付失败率上升等),我们往往缺乏直观的数据支撑。

业务指标监控能帮助我们:

  • 快速发现业务异常
  • 了解业务发展趋势
  • 为业务决策提供数据支持
  • 实现精细化运营

整体架构设计

我们的监控方案由以下几个组件构成:

  1. Micrometer:作为指标收集的抽象层,屏蔽底层监控系统的差异
  2. Spring Boot:提供应用框架和Actuator端点
  3. Prometheus:负责指标的存储和查询
  4. Grafana:提供可视化的图表展示

让我们看看如何在SpringBoot中实现这套监控系统:

1. 添加依赖

首先在pom.xml中添加必要的监控依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-core</artifactId>
</dependency>

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

2. 配置应用

在application.yml中配置监控相关设置:

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: always
  metrics:
    export:
      prometheus:
        enabled: true

3. 创建业务指标收集器

定义一个专门收集业务指标的类:

@Component
@RequiredArgsConstructor
@Slf4j
public class BusinessMetricsCollector implements MeterBinder {
    
    private final MeterRegistry meterRegistry;
    
    // 订单总数计数器
    private Counter orderTotalCounter;
    
    // 订单失败计数器
    private Counter orderFailedCounter;
    
    // 订单成功计数器
    private Counter orderSuccessCounter;
    
    // 订单处理时间计时器
    private Timer orderProcessingTimer;
    
    // 订单成功率
    private AtomicLong successRateGauge;
    
    @PostConstruct
    public void initializeMetrics() {
        // 初始化订单总数计数器
        orderTotalCounter = Counter.builder("business_orders_total")
                .description("订单总数")
                .tag("type", "business")
                .register(meterRegistry);
        
        // 初始化订单失败计数器
        orderFailedCounter = Counter.builder("business_order_failed_total")
                .description("订单失败总数")
                .tag("type", "business")
                .register(meterRegistry);
        
        // 初始化订单处理时间计时器
        orderProcessingTimer = Timer.builder("business_order_processing_duration_seconds")
                .description("订单处理耗时")
                .register(meterRegistry);
        
        // 注册订单成功率仪表盘
        successRateGauge = new AtomicLong(100); // 默认100%
        Gauge.builder("business_order_success_rate")
                .description("订单成功率")
                .register(meterRegistry, successRateGauge, AtomicLong::get);
    }
    
    /**
     * 记录新订单
     */
    public void recordNewOrder(double amount) {
        orderTotalCounter.increment();
        log.debug("记录新订单,金额: {}", amount);
    }
    
    /**
     * 记录订单成功
     */
    public void recordOrderSuccess() {
        orderSuccessCounter.increment();
        updateSuccessRate();
        log.debug("记录订单成功");
    }
    
    /**
     * 记录订单失败
     */
    public void recordOrderFailed() {
        orderFailedCounter.increment();
        updateSuccessRate();
        log.debug("记录订单失败");
    }
    
    /**
     * 记录订单处理时间
     */
    public void recordOrderProcessingTime(long durationMs) {
        orderProcessingTimer.record(durationMs, java.util.concurrent.TimeUnit.MILLISECONDS);
        log.debug("记录订单处理时间: {} ms", durationMs);
    }
    
    /**
     * 更新订单成功率
     */
    private void updateSuccessRate() {
        long total = (long) orderTotalCounter.count();
        if (total > 0) {
            long success = (long) orderSuccessCounter.count();
            double rate = (double) success / total * 100;
            successRateGauge.set(Math.round(rate));
        }
    }
}

4. 在业务服务中使用指标

在订单服务中集成指标收集:

@Service
@RequiredArgsConstructor
@Slf4j
public class OrderService {
    
    private final OrderRepository orderRepository;
    
    @Autowired
    private BusinessMetricsCollector metricsCollector;
    
    /**
     * 创建订单
     * 使用@Timed注解监控方法执行时间
     */
    @Timed(value = "order_creation_time", description = "订单创建耗时")
    @Transactional
    public Order createOrder(Long customerId, BigDecimal amount) {
        long startTime = System.currentTimeMillis();
        
        try {
            // 业务逻辑...
            
            // 保存订单
            Order savedOrder = orderRepository.save(order);
            
            // 记录业务指标
            metricsCollector.recordNewOrder(amount.doubleValue());
            
            return savedOrder;
        } catch (Exception e) {
            log.error("订单创建失败", e);
            // 记录失败指标
            metricsCollector.recordOrderFailed();
            throw e;
        } finally {
            long duration = System.currentTimeMillis() - startTime;
            metricsCollector.recordOrderProcessingTime(duration);
        }
    }
    
    /**
     * 处理订单支付
     */
    @Timed(value = "order_payment_processing_time", description = "订单支付处理耗时")
    @Transactional
    public Order processPayment(String orderNumber) {
        long startTime = System.currentTimeMillis();
        
        try {
            // 业务逻辑...
            
            // 更新订单状态
            Order updatedOrder = orderRepository.save(order);
            
            // 记录成功指标
            metricsCollector.recordOrderSuccess();
            
            return updatedOrder;
        } catch (Exception e) {
            log.error("订单支付处理失败", e);
            // 记录失败指标
            metricsCollector.recordOrderFailed();
            throw e;
        } finally {
            long duration = System.currentTimeMillis() - startTime;
            metricsCollector.recordOrderProcessingTime(duration);
        }
    }
}

5. 提供指标查询接口

创建一个专门的控制器来提供业务指标查询:

@RestController
@RequestMapping("/api/orders")
public class OrderController {
    
    @Autowired
    private BusinessMetricsCollector metricsCollector;
    
    /**
     * 获取业务指标
     */
    @GetMapping("/metrics/business")
    public ResponseEntity<Map<String, Object>> getBusinessMetrics() {
        Map<String, Object> metrics = Map.of(
            "totalOrders", metricsCollector.getTotalOrders(),
            "successOrders", metricsCollector.getSuccessOrders(),
            "failedOrders", metricsCollector.getFailedOrders(),
            "successRate", metricsCollector.getCurrentSuccessRate()
        );
        
        return ResponseEntity.ok(metrics);
    }
}

Prometheus配置

为了让Prometheus能够收集我们的指标数据,需要在Prometheus配置文件中添加抓取任务:

scrape_configs:
  - job_name: 'monitoring-app'
    static_configs:
      - targets: ['localhost:8080']
    metrics_path: '/actuator/prometheus'
    scrape_interval: 15s

这样Prometheus就会定期从我们的应用中拉取指标数据。

Grafana可视化

在Grafana中,我们可以创建丰富的仪表盘来展示业务指标:

  1. 添加Prometheus作为数据源
  2. 创建新的仪表盘
  3. 添加面板并配置查询语句

常用的查询语句示例:

  • 订单总数:business_orders_total
  • 订单成功率:business_order_success_rate
  • API响应时间:http_server_requests_seconds_sum / http_server_requests_seconds_count

监控最佳实践

  1. 指标命名规范:使用有意义的指标名称,如business_orders_total,遵循snake_case命名法
  2. 标签使用:合理使用标签来区分不同维度的数据,如环境、服务名等
  3. 性能考虑:避免在高频调用的方法中收集过多指标,以免影响性能
  4. 告警设置:为关键指标设置告警阈值,如订单失败率超过5%时告警
  5. 数据保留:配置合适的数据保留策略,平衡存储成本和查询需求

实际应用场景

这套监控方案特别适用于以下场景:

  1. 电商平台:监控订单量、支付成功率、退款率等
  2. 金融服务:监控交易量、成功率、平均处理时间等
  3. 在线教育:监控课程报名量、完课率、活跃用户数等
  4. 游戏平台:监控用户登录数、付费转化率、道具购买量等

总结

通过SpringBoot + Micrometer + Prometheus + Grafana的组合,我们可以轻松构建一套功能强大的业务指标监控系统。这套方案具有以下优点:

  • 标准化:Micrometer提供了统一的指标收集接口
  • 可扩展:易于添加新的业务指标
  • 可视化:Grafana提供了丰富的图表展示
  • 告警能力:可以基于指标设置告警规则

在实际项目中,建议从最关键的业务指标开始监控,逐步扩展到更多的业务维度。只有建立了完善的监控体系,我们才能真正做到心中有数,从容应对各种业务挑战。

希望这篇文章能对你有所帮助,如果你觉得有用,欢迎关注"服务端技术精选",我会持续分享更多实用的技术干货。


标题:SpringBoot + Micrometer + Prometheus + Grafana:自定义业务指标监控
作者:jiangyi
地址:http://www.jiangyi.space/articles/2026/02/02/1769851164852.html
公众号:服务端技术精选
    评论
    0 评论
avatar

取消