Java指标统计案例怎么实操

wen java案例 31

本文目录导读:

Java指标统计案例怎么实操

  1. 基础实现方案
  2. 使用Micrometer(推荐的生产方案)
  3. Spring Boot集成方案
  4. 实际监控示例
  5. Prometheus + Grafana可视化
  6. 最佳实践建议

我来给你一个完整的Java指标统计(Metrics)实操案例,从基础到进阶。

基础实现方案

简单的计数器实现

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
public class SimpleMetrics {
    // 原子计数器
    private AtomicLong requestCount = new AtomicLong(0);
    private AtomicLong successCount = new AtomicLong(0);
    private AtomicLong failureCount = new AtomicLong(0);
    // 耗时统计(毫秒)
    private AtomicLong totalTime = new AtomicLong(0);
    // 记录请求
    public void recordRequest() {
        requestCount.incrementAndGet();
    }
    // 记录成功
    public void recordSuccess(long timeCost) {
        successCount.incrementAndGet();
        totalTime.addAndGet(timeCost);
    }
    // 记录失败
    public void recordFailure() {
        failureCount.incrementAndGet();
    }
    // 获取统计信息
    public Map<String, Object> getStats() {
        Map<String, Object> stats = new HashMap<>();
        long total = requestCount.get();
        long success = successCount.get();
        long failure = failureCount.get();
        stats.put("totalRequests", total);
        stats.put("successCount", success);
        stats.put("failureCount", failure);
        stats.put("successRate", total > 0 ? (double)success/total * 100 : 0);
        stats.put("averageTime", success > 0 ? totalTime.get()/success : 0);
        return stats;
    }
}

使用示例

public class MetricsDemo {
    public static void main(String[] args) throws InterruptedException {
        SimpleMetrics metrics = new SimpleMetrics();
        // 模拟请求
        for (int i = 0; i < 100; i++) {
            metrics.recordRequest();
            long startTime = System.currentTimeMillis();
            try {
                // 模拟业务处理
                Thread.sleep((long)(Math.random() * 100));
                if (Math.random() > 0.1) { // 90%成功率
                    metrics.recordSuccess(System.currentTimeMillis() - startTime);
                } else {
                    metrics.recordFailure();
                }
            } catch (Exception e) {
                metrics.recordFailure();
            }
        }
        // 输出统计结果
        System.out.println("统计结果: " + metrics.getStats());
    }
}

使用Micrometer(推荐的生产方案)

引入依赖

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-core</artifactId>
    <version>1.12.0</version>
</dependency>
<!-- 如果需要Prometheus输出 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <version>1.12.0</version>
</dependency>

业务指标监控类

import io.micrometer.core.instrument.*;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
public class BusinessMetrics {
    private final MeterRegistry registry;
    // 计数器示例
    private final Counter orderCounter;
    private final Counter paymentCounter;
    private final Counter refundCounter;
    // 仪表盘示例(实时值)
    private final Gauge activeUsers;
    private final Gauge queueSize;
    // 计时器示例
    private final Timer orderProcessTime;
    private final Timer paymentProcessTime;
    // 分布摘要示例(延迟分布)
    private final DistributionSummary orderAmount;
    // 自定义状态
    private final AtomicLong activeUsersValue = new AtomicLong(0);
    private final AtomicLong queueSizeValue = new AtomicLong(0);
    public BusinessMetrics(MeterRegistry registry) {
        this.registry = registry;
        // 初始化计数器
        orderCounter = Counter.builder("orders.total")
                .description("总订单数")
                .tag("type", "business")
                .register(registry);
        paymentCounter = Counter.builder("payments.total")
                .description("总支付数")
                .register(registry);
        refundCounter = Counter.builder("refunds.total")
                .description("总退款数")
                .register(registry);
        // 初始化Gauge
        activeUsers = Gauge.builder("users.active", activeUsersValue, 
                AtomicLong::doubleValue)
                .description("活跃用户数")
                .register(registry);
        queueSize = Gauge.builder("queue.size", queueSizeValue, 
                AtomicLong::doubleValue)
                .description("队列大小")
                .register(registry);
        // 初始化Timer
        orderProcessTime = Timer.builder("order.process.time")
                .description("订单处理时间")
                .publishPercentiles(0.5, 0.95, 0.99)
                .publishPercentileHistogram()
                .register(registry);
        paymentProcessTime = Timer.builder("payment.process.time")
                .description("支付处理时间")
                .register(registry);
        // 初始化DistributionSummary
        orderAmount = DistributionSummary.builder("order.amount")
                .description("订单金额分布")
                .publishPercentiles(0.5, 0.75, 0.9, 0.99)
                .register(registry);
    }
    // 记录订单
    public void recordOrder() {
        orderCounter.increment();
    }
    // 记录支付
    public void recordPayment() {
        paymentCounter.increment();
    }
    // 记录订单处理时间
    public void recordOrderProcessTime(long duration, TimeUnit unit) {
        orderProcessTime.record(duration, unit);
    }
    // 带lambda的计时方式
    public <T> T recordOrderProcess(Supplier<T> supplier) {
        return orderProcessTime.record(supplier);
    }
    // 记录订单金额
    public void recordOrderAmount(double amount) {
        orderAmount.record(amount);
    }
    // 更新活跃用户数
    public void updateActiveUsers(int count) {
        activeUsersValue.set(count);
    }
    // 更新队列大小
    public void updateQueueSize(int size) {
        queueSizeValue.set(size);
    }
}

实际业务使用

import java.time.LocalDateTime;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class MetricsService {
    private final BusinessMetrics metrics;
    private final Random random = new Random();
    public MetricsService(MeterRegistry registry) {
        this.metrics = new BusinessMetrics(registry);
    }
    // 订单处理
    public void processOrder(Order order) {
        long startTime = System.nanoTime();
        try {
            // 模拟业务处理
            Thread.sleep(random.nextInt(200));
            // 记录订单
            metrics.recordOrder();
            metrics.recordOrderAmount(order.getAmount());
            // 记录处理时间
            metrics.recordOrderProcessTime(
                System.nanoTime() - startTime, 
                TimeUnit.NANOSECONDS
            );
        } catch (Exception e) {
            // 错误处理
        }
    }
    // 支付处理
    public void processPayment(Payment payment) {
        long startTime = System.nanoTime();
        try {
            // 模拟支付处理
            Thread.sleep(random.nextInt(100));
            // 记录支付
            metrics.recordPayment();
            // 记录处理时间
            metrics.recordOrderProcessTime(
                System.nanoTime() - startTime, 
                TimeUnit.NANOSECONDS
            );
        } catch (Exception e) {
            // 错误处理
        }
    }
    // 更新系统状态
    public void updateSystemStatus() {
        metrics.updateActiveUsers(random.nextInt(10000));
        metrics.updateQueueSize(random.nextInt(1000));
    }
}

Spring Boot集成方案

添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

配置属性

# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  metrics:
    tags:
      application: ${spring.application.name}
    export:
      prometheus:
        enabled: true
        step: 1m
# 自定义指标标签
spring:
  application:
    name: metrics-demo

自定义指标注册

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;
@Component
public class CustomMetricsCollector {
    private final MeterRegistry meterRegistry;
    public CustomMetricsCollector(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        initializeMetrics();
    }
    private void initializeMetrics() {
        // 注册自定义指标
        meterRegistry.gauge("custom.metric.value", Tags.of("type", "business"), 
            this, CustomMetricsCollector::getCustomValue);
    }
    private double getCustomValue() {
        // 返回实际的指标值
        return Math.random() * 100;
    }
}

定时任务收集指标

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MetricScheduledTask {
    private final MeterRegistry meterRegistry;
    public MetricScheduledTask(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    public void collectMetrics() {
        // 收集JVM内存指标
        meterRegistry.gauge("jvm.memory.used", 
            Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
        // 收集线程指标
        meterRegistry.gauge("thread.active.count", 
            (double) Thread.activeCount());
        // 收集自定义业务指标
        // ...
    }
}

实际监控示例

完整的API监控

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class ApiMetricsController {
    private final MeterRegistry meterRegistry;
    private final Counter apiCallCounter;
    private final Counter errorCounter;
    private final Timer responseTime;
    public ApiMetricsController(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.apiCallCounter = Counter.builder("api.calls.total")
                .description("API调用次数")
                .register(meterRegistry);
        this.errorCounter = Counter.builder("api.errors.total")
                .description("API错误次数")
                .register(meterRegistry);
        this.responseTime = Timer.builder("api.response.time")
                .description("API响应时间")
                .publishPercentiles(0.5, 0.95, 0.99)
                .register(meterRegistry);
    }
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        Timer.Sample sample = Timer.start(meterRegistry);
        try {
            apiCallCounter.increment();
            // 业务逻辑
            User user = findUser(id);
            sample.stop(responseTime);
            return user;
        } catch (Exception e) {
            errorCounter.increment();
            sample.stop(responseTime);
            throw e;
        }
    }
}

数据库监控

@Component
public class DatabaseMetrics {
    private final MeterRegistry meterRegistry;
    private final Timer queryTimer;
    private final Counter queryCounter;
    private final Counter slowQueryCounter;
    public DatabaseMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.queryTimer = Timer.builder("db.query.time")
                .description("数据库查询时间")
                .register(meterRegistry);
        this.queryCounter = Counter.builder("db.query.total")
                .description("数据库查询次数")
                .register(meterRegistry);
        this.slowQueryCounter = Counter.builder("db.slow.query.total")
                .description("慢查询次数")
                .register(meterRegistry);
    }
    public <T> T recordQuery(String queryName, Supplier<T> query) {
        queryCounter.increment();
        return queryTimer.record(() -> {
            long startTime = System.currentTimeMillis();
            T result = query.get();
            long duration = System.currentTimeMillis() - startTime;
            if (duration > 1000) { // 超过1秒的慢查询
                slowQueryCounter.increment();
                log.warn("慢查询: {} 耗时: {}ms", queryName, duration);
            }
            return result;
        });
    }
}

Prometheus + Grafana可视化

Prometheus配置

# prometheus.yml
scrape_configs:
  - job_name: 'java-app'
    metrics_path: '/actuator/prometheus'
    scrape_interval: 15s
    static_configs:
      - targets: ['localhost:8080']

Grafana Dashboard配置示例

{
  "panels": [
    {
      "title": "API请求率",
      "type": "graph",
      "targets": [
        {
          "expr": "rate(api_calls_total[5m])",
          "legendFormat": "请求率"
        }
      ]
    },
    {
      "title": "响应时间P99",
      "type": "graph",
      "targets": [
        {
          "expr": "histogram_quantile(0.99, rate(api_response_time_seconds_bucket[5m]))",
          "legendFormat": "P99"
        }
      ]
    }
  ]
}

最佳实践建议

选择合适的指标类型

  • Counter: 只增不减的计数(请求数、错误数)
  • Gauge: 可增可减的瞬时值(内存使用、连接数)
  • Timer: 耗时统计(请求延迟、执行时间)
  • DistributionSummary: 数值分布(请求大小、金额)

性能优化

  • 使用原子操作(AtomicLong)而不是锁
  • 批量处理指标数据
  • 异步采集非关键指标

监控要点

  • 核心业务指标(订单量、转化率)
  • 系统资源(CPU、内存、磁盘)
  • 应用性能(响应时间、吞吐量)
  • 错误监控(异常频率、错误类型)

告警设置

# 告警规则示例
groups:
  - name: java_app_alerts
    rules:
      - alert: HighErrorRate
        expr: rate(error_count_total[5m]) > 0.1
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "错误率过高"

这套方案可以应对大部分Java应用的指标监控需求,根据实际场景,你可以选择简单计数器或完整的Micrometer方案。

抱歉,评论功能暂时关闭!