本文目录导读:

我来给你一个完整的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方案。