Spring Boot Actuator生产实践:构建企业级应用监控体系

# Spring Boot Actuator生产实践:构建企业级应用监控体系


在现代云原生应用架构中,全面的监控和健康检查是保障系统稳定性的关键要素。Spring Boot Actuator作为应用程序监控的事实标准,通过丰富的端点提供了对应用运行状态的深度洞察。


## Actuator核心配置与自定义端点


Spring Boot Actuator 3.x提供了标准化的监控端点,支持通过HTTP和JMX两种方式暴露指标。


```yaml

# application-actuator.yml - Actuator配置

management:

  endpoints:

    web:

      exposure:

        include: health,info,metrics,prometheus,loggers,env,configprops

        exclude: shutdown

      base-path: /management

      path-mapping:

        health: health-check

        metrics: application-metrics

      access:

        rules:

          - endpoint: health

            access: unrestricted

          - endpoint: info

            access: unrestricted

          - endpoint: metrics

            access: authenticated

          - endpoint: env

            access: admin

          - endpoint: loggers

            access: admin

      cors:

        allowed-origins: "https://monitor.example.com"

        allowed-methods: "GET,POST"

    

    jmx:

      exposure:

        include: "*"

      domain: "com.example.app"

      unique-names: true

    

  endpoint:

    health:

      enabled: true

      show-details: when-authorized

      show-components: when-authorized

      roles: ADMIN, MONITOR

      probes:

        enabled: true

        group:

          liveness:

            enabled: true

            include: ping,livenessState,diskSpace

          readiness:

            enabled: true

            include: ping,readinessState,db,cache,mq

    

    metrics:

      enabled: true

      distribution:

        percentiles-histogram:

          http.server.requests: true

          jvm.gc.pause: true

        slo:

          http.server.requests: 100ms,200ms,500ms,1s

    

    prometheus:

      enabled: true

      step: 1m

      descriptions: true

    

    loggers:

      enabled: true

      cache:

        time-to-live: 10s

    

    env:

      enabled: true

      post:

        enabled: true

    

    configprops:

      enabled: true

      prefixes: spring.datasource,spring.redis,spring.cache

    

  health:

    db:

      enabled: true

      validation-query: "SELECT 1"

      timeout: 3s

    redis:

      enabled: true

      timeout: 2s

    diskspace:

      enabled: true

      threshold: 10MB

    mail:

      enabled: false

    elasticsearch:

      enabled: false

    

  metrics:

    enable:

      all: true

    export:

      prometheus:

        enabled: true

        step: 1m

        descriptions: true

      influx:

        enabled: false

      datadog:

        enabled: false

    tags:

      application: ${spring.application.name}

      environment: ${spring.profiles.active:default}

      region: ${CLOUD_REGION:local}

      instance: ${HOSTNAME:${spring.application.instance-id:${random.value}}}

    distribution:

      percentiles:

        http.server.requests: 0.5,0.95,0.99

      percentiles-histogram:

        http.server.requests: true

    

  server:

    port: 8081

    address: 127.0.0.1

    ssl:

      enabled: true

      key-store: classpath:keystore.p12

      key-store-password: ${SSL_PASSWORD}

      key-store-type: PKCS12

    compression:

      enabled: true

      mime-types: application/json,text/plain

      min-response-size: 1024

    

  tracing:

    sampling:

      probability: 0.1

    propagation:

      type: B3

    baggage:

      correlation:

        fields: userId,traceId,spanId

    

  info:

    env:

      enabled: true

    java:

      enabled: true

    os:

      enabled: true

    build:

      enabled: true

    git:

      mode: full


spring:

  security:

    user:

      name: actuator

      password: ${ACTUATOR_PASSWORD:changeit}

  application:

    name: product-service

```


## 自定义健康检查指标实现


```java

// CustomHealthIndicator.java - 自定义健康检查

package com.example.monitor.health;


import org.springframework.boot.actuate.health.*;

import org.springframework.boot.actuate.health.Health.Builder;

import org.springframework.stereotype.Component;

import org.springframework.data.redis.connection.RedisConnectionFactory;

import org.springframework.jdbc.core.JdbcTemplate;


import java.sql.Connection;

import java.time.Duration;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.TimeoutException;


@Component

@Slf4j

public class CustomHealthIndicator extends AbstractHealthIndicator {

    

    private final JdbcTemplate jdbcTemplate;

    private final RedisConnectionFactory redisConnectionFactory;

    private final ExternalServiceClient externalServiceClient;

    private final CacheManager cacheManager;

    private final ExecutorService healthCheckExecutor;

    

    // 健康检查结果缓存

    private final Map healthCache = new ConcurrentHashMap<>();

    

    public CustomHealthIndicator(JdbcTemplate jdbcTemplate,

                                 RedisConnectionFactory redisConnectionFactory,

                                 ExternalServiceClient externalServiceClient,

                                 CacheManager cacheManager) {

        this.jdbcTemplate = jdbcTemplate;

        this.redisConnectionFactory = redisConnectionFactory;

        this.externalServiceClient = externalServiceClient;

        this.cacheManager = cacheManager;

        this.healthCheckExecutor = Executors.newFixedThreadPool(5);

        

        // 设置超时保护

        super.setTimeout(Duration.ofSeconds(10));

    }

    

    @Override

    protected void doHealthCheck(Builder builder) throws Exception {

        log.debug("开始执行健康检查");

        

        builder.withDetail("timestamp", System.currentTimeMillis());

        builder.withDetail("thread", Thread.currentThread().getName());

        

        // 检查数据库连接

        checkDatabaseHealth(builder);

        

        // 检查Redis连接

        checkRedisHealth(builder);

        

        // 检查外部服务

        checkExternalServices(builder);

        

        // 检查缓存状态

        checkCacheHealth(builder);

        

        // 检查磁盘空间

        checkDiskSpace(builder);

        

        // 检查JVM状态

        checkJvmHealth(builder);

        

        // 检查线程池状态

        checkThreadPoolHealth(builder);

        

        // 检查消息队列连接

        checkMessageQueueHealth(builder);

        

        // 检查配置文件

        checkConfigurationHealth(builder);

        

        // 标记整体状态

        determineOverallStatus(builder);

        

        log.info("健康检查完成,状态: {}", builder.build().getStatus());

    }

    

    private void checkDatabaseHealth(Builder builder) {

        try {

            Future future = healthCheckExecutor.submit(() -> {

                try (Connection conn = jdbcTemplate.getDataSource().getConnection()) {

                    jdbcTemplate.queryForObject("SELECT 1", Integer.class);

                    return true;

                }

            });

            

            boolean isHealthy = future.get(3, TimeUnit.SECONDS);

            if (isHealthy) {

                builder.withDetail("database.status", "UP");

                builder.withDetail("database.responseTime", "正常");

                

                // 获取数据库连接池信息

                Map poolInfo = jdbcTemplate.queryForMap(

                    "SHOW STATUS LIKE 'Threads_connected'"

                );

                builder.withDetail("database.connections", poolInfo);

            }

        } catch (TimeoutException e) {

            builder.withDetail("database.status", "DOWN");

            builder.withDetail("database.error", "连接超时");

            builder.down().withException(e);

        } catch (Exception e) {

            builder.withDetail("database.status", "DOWN");

            builder.withDetail("database.error", e.getMessage());

            builder.down().withException(e);

        }

    }

    

    private void checkRedisHealth(Builder builder) {

        try {

            Future future = healthCheckExecutor.submit(() -> {

                var connection = redisConnectionFactory.getConnection();

                String pong = connection.ping();

                connection.close();

                return "PONG".equals(pong);

            });

            

            boolean isHealthy = future.get(2, TimeUnit.SECONDS);

            if (isHealthy) {

                builder.withDetail("redis.status", "UP");

                builder.withDetail("redis.response", "PONG");

                

                // 获取Redis内存信息

                var connection = redisConnectionFactory.getConnection();

                Properties info = connection.info("memory");

                builder.withDetail("redis.memory", info.getProperty("used_memory_human"));

                connection.close();

            }

        } catch (Exception e) {

            builder.withDetail("redis.status", "DOWN");

            builder.withDetail("redis.error", e.getMessage());

        }

    }

    

    private void checkExternalServices(Builder builder) {

        Map services = Map.of(

            "payment-service", "http://payment-service:8080/actuator/health",

            "inventory-service", "http://inventory-service:8080/actuator/health",

            "notification-service", "http://notification-service:8080/actuator/health"

        );

        

        services.forEach((serviceName, url) -> {

            try {

                ServiceHealth health = externalServiceClient.checkHealth(url);

                builder.withDetail(serviceName + ".status", health.getStatus());

                builder.withDetail(serviceName + ".responseTime", health.getResponseTime() + "ms");

                

                if (health.getDetails() != null) {

                    builder.withDetail(serviceName + ".details", health.getDetails());

                }

            } catch (Exception e) {

                builder.withDetail(serviceName + ".status", "DOWN");

                builder.withDetail(serviceName + ".error", e.getMessage());

            }

        });

    }

    

    private void checkCacheHealth(Builder builder) {

        try {

            Cache cache = cacheManager.getCache("products");

            if (cache != null) {

                long hitCount = cache.getStatistics().getHitCount();

                long missCount = cache.getStatistics().getMissCount();

                long size = cache.getStatistics().getSize();

                

                builder.withDetail("cache.status", "UP");

                builder.withDetail("cache.hitCount", hitCount);

                builder.withDetail("cache.missCount", missCount);

                builder.withDetail("cache.size", size);

                

                // 计算命中率

                if (hitCount + missCount > 0) {

                    double hitRate = (double) hitCount / (hitCount + missCount) * 100;

                    builder.withDetail("cache.hitRate", String.format("%.2f%%", hitRate));

                }

            }

        } catch (Exception e) {

            builder.withDetail("cache.status", "UNKNOWN");

            builder.withDetail("cache.error", e.getMessage());

        }

    }

    

    private void checkDiskSpace(Builder builder) {

        try {

            File root = new File("/");

            long totalSpace = root.getTotalSpace();

            long freeSpace = root.getFreeSpace();

            long usableSpace = root.getUsableSpace();

            

            builder.withDetail("disk.total", formatBytes(totalSpace));

            builder.withDetail("disk.free", formatBytes(freeSpace));

            builder.withDetail("disk.usable", formatBytes(usableSpace));

            

            // 计算使用率

            double usagePercentage = (double) (totalSpace - usableSpace) / totalSpace * 100;

            builder.withDetail("disk.usage", String.format("%.2f%%", usagePercentage));

            

            // 预警:磁盘使用率超过90%

            if (usagePercentage > 90) {

                builder.withDetail("disk.status", "WARNING");

                builder.withDetail("disk.warning", "磁盘空间不足");

            } else {

                builder.withDetail("disk.status", "UP");

            }

        } catch (Exception e) {

            builder.withDetail("disk.status", "UNKNOWN");

            builder.withDetail("disk.error", e.getMessage());

        }

    }

    

    private void checkJvmHealth(Builder builder) {

        Runtime runtime = Runtime.getRuntime();

        

        long maxMemory = runtime.maxMemory();

        long totalMemory = runtime.totalMemory();

        long freeMemory = runtime.freeMemory();

        long usedMemory = totalMemory - freeMemory;

        

        builder.withDetail("jvm.memory.max", formatBytes(maxMemory));

        builder.withDetail("jvm.memory.total", formatBytes(totalMemory));

        builder.withDetail("jvm.memory.used", formatBytes(usedMemory));

        builder.withDetail("jvm.memory.free", formatBytes(freeMemory));

        

        // 计算内存使用率

        double memoryUsage = (double) usedMemory / totalMemory * 100;

        builder.withDetail("jvm.memory.usage", String.format("%.2f%%", memoryUsage));

        

        // 线程信息

        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

        builder.withDetail("jvm.threads.total", threadMXBean.getThreadCount());

        builder.withDetail("jvm.threads.daemon", threadMXBean.getDaemonThreadCount());

        <"d0.p5k3.org.cn"><"h4.p5k3.org.cn"><"v6.p5k3.org.cn">

        // GC信息

        List gcBeans = ManagementFactory.getGarbageCollectorMXBeans();

        for (GarbageCollectorMXBean gcBean : gcBeans) {

            builder.withDetail("jvm.gc." + gcBean.getName() + ".count", gcBean.getCollectionCount());

            builder.withDetail("jvm.gc." + gcBean.getName() + ".time", gcBean.getCollectionTime() + "ms");

        }

        

        // 预警:内存使用率超过85%

        if (memoryUsage > 85) {

            builder.withDetail("jvm.status", "WARNING");

            builder.withDetail("jvm.warning", "内存使用率过高");

        } else {

            builder.withDetail("jvm.status", "UP");

        }

    }

    

    private void checkThreadPoolHealth(Builder builder) {

        try {

            ThreadPoolExecutor executor = (ThreadPoolExecutor) healthCheckExecutor;

            

            builder.withDetail("threadPool.coreSize", executor.getCorePoolSize());

            builder.withDetail("threadPool.maxSize", executor.getMaximumPoolSize());

            builder.withDetail("threadPool.active", executor.getActiveCount());

            builder.withDetail("threadPool.queueSize", executor.getQueue().size());

            builder.withDetail("threadPool.completed", executor.getCompletedTaskCount());

            

            // 计算线程池使用率

            double poolUsage = (double) executor.getActiveCount() / executor.getMaximumPoolSize() * 100;

            builder.withDetail("threadPool.usage", String.format("%.2f%%", poolUsage));

            

            if (poolUsage > 80) {

                builder.withDetail("threadPool.status", "WARNING");

                builder.withDetail("threadPool.warning", "线程池使用率过高");

            } else {

                builder.withDetail("threadPool.status", "UP");

            }

        } catch (Exception e) {

            builder.withDetail("threadPool.status", "UNKNOWN");

            builder.withDetail("threadPool.error", e.getMessage());

        }

    }

    

    private void determineOverallStatus(Builder builder) {

        Health health = builder.build();

        Map details = health.getDetails();

        

        // 分析各个组件的状态

        long downCount = details.values().stream()

            .filter(value -> value instanceof Map)

            .map(value -> (Map) value)

            .filter(map -> "DOWN".equals(map.get("status")))

            .count();

        

        long warningCount = details.values().stream()

            .filter(value -> value instanceof Map)

            .map(value -> (Map) value)

            .filter(map -> "WARNING".equals(map.get("status")))

            .count();

        

        if (downCount > 0) {

            builder.down()

                .withDetail("overall.status", "DOWN")

                .withDetail("down.components", downCount)

                .withDetail("warning.components", warningCount);

        } else if (warningCount > 0) {

            builder.status("WARNING")

                .withDetail("overall.status", "WARNING")

                .withDetail("warning.components", warningCount);

        } else {

            builder.up()

                .withDetail("overall.status", "UP")

                .withDetail("checked.components", details.size());

        }

    }

    

    private String formatBytes(long bytes) {

        if (bytes < 1024) return bytes + " B";

        int exp = (int) (Math.log(bytes) / Math.log(1024));

        char pre = "KMGTPE".charAt(exp - 1);

        return String.format("%.2f %sB", bytes / Math.pow(1024, exp), pre);

    }

    

    @PreDestroy

    public void cleanup() {

        if (healthCheckExecutor != null) {

            healthCheckExecutor.shutdown();

            try {

                if (!healthCheckExecutor.awaitTermination(5, TimeUnit.SECONDS)) {

                    healthCheckExecutor.shutdownNow();

                }

            } catch (InterruptedException e) {

                healthCheckExecutor.shutdownNow();

                Thread.currentThread().interrupt();

            }

        }

    }

}


// 业务服务健康检查

@Component

public class BusinessHealthIndicator extends AbstractHealthIndicator {

    

    private final OrderRepository orderRepository;

    private final ProductService productService;

    private final MessageQueueService mqService;

    

    @Override

    protected void doHealthCheck(Builder builder) throws Exception {

        builder.withDetail("service", "business-services");

        

        // 检查订单处理能力

        checkOrderProcessing(builder);

        

        // 检查商品服务

        checkProductService(builder);

        

        // 检查消息队列

        checkMessageQueue(builder);

        

        // 检查批处理任务

        checkBatchJobs(builder);

    }

    

    private void checkOrderProcessing(Builder builder) {

        try {

            // 检查最近订单处理情况

            LocalDateTime >

            long totalOrders = orderRepository.countByCreatedAtAfter(oneHourAgo);

            long pendingOrders = orderRepository.countByStatusAndCreatedAtAfter(

                OrderStatus.PENDING, oneHourAgo);

            

            builder.withDetail("orders.lastHour.total", totalOrders);

            builder.withDetail("orders.lastHour.pending", pendingOrders);

            

            // 计算处理延迟

            if (totalOrders > 0) {

                double pendingRate = (double) pendingOrders / totalOrders * 100;

                builder.withDetail("orders.pendingRate", String.format("%.2f%%", pendingRate));

                

                if (pendingRate > 20) {

                    builder.withDetail("orders.status", "WARNING");

                    builder.withDetail("orders.warning", "待处理订单过多");

                } else {

                    builder.withDetail("orders.status", "UP");

                }

            }

        } catch (Exception e) {

            builder.withDetail("orders.status", "DOWN");

            builder.withDetail("orders.error", e.getMessage());

        }

    }

    

    private void checkProductService(Builder builder) {

        try {

            // 检查商品库存

            List lowStockProducts = productService.findLowStockProducts(10);

            builder.withDetail("products.lowStock.count", lowStockProducts.size());

            

            // 检查商品价格同步

            boolean priceSyncHealthy = productService.isPriceSyncHealthy();

            builder.withDetail("products.priceSync", priceSyncHealthy ? "UP" : "DOWN");

            

            if (!priceSyncHealthy) {

                builder.withDetail("products.warning", "价格同步异常");

            }

        } catch (Exception e) {

            builder.withDetail("products.status", "DOWN");

            builder.withDetail("products.error", e.getMessage());

        }

    }

    

    private void checkMessageQueue(Builder builder) {

        try {

            MessageQueueStats stats = mqService.getQueueStats();

            

            builder.withDetail("mq.totalMessages", stats.getTotalMessages());

            builder.withDetail("mq.consumers", stats.getActiveConsumers());

            builder.withDetail("mq.pending", stats.getPendingMessages());

            

            // 检查消息积压

            if (stats.getPendingMessages() > 1000) {

                builder.withDetail("mq.status", "WARNING");

                builder.withDetail("mq.warning", "消息积压严重");

            } else {

                builder.withDetail("mq.status", "UP");

            }

        } catch (Exception e) {

            builder.withDetail("mq.status", "DOWN");

            builder.withDetail("mq.error", e.getMessage());

        }

    }

}

```


## Kubernetes就绪性与活性探针


```yaml

# k8s-deployment.yaml - Kubernetes探针配置

apiVersion: apps/v1

kind: Deployment

metadata:

  name: product-service

  namespace: production

  labels:

    app: product-service

spec:

  replicas: 3

  selector:

    matchLabels:

      app: product-service

  template:

    metadata:

      labels:

        app: product-service

      annotations:

        prometheus.io/scrape: "true"

        prometheus.io/path: "/management/prometheus"

        prometheus.io/port: "8081"

    spec:

      containers:

      - name: product-service

        image: registry.example.com/product-service:1.0.0

        ports:

        - containerPort: 8080

          name: http

        - containerPort: 8081

          name: management

        env:

        - name: SPRING_PROFILES_ACTIVE

          value: "production"

        - name: MANAGEMENT_SERVER_PORT

          value: "8081"

        - name: MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE

          value: "health,info,metrics,prometheus"

        - name: MANAGEMENT_ENDPOINT_HEALTH_SHOWDETAILS

          value: "always"

        - name: MANAGEMENT_ENDPOINT_HEALTH_PROBES_ENABLED

          value: "true"

        

        # 存活探针(Liveness Probe)

        livenessProbe:

          httpGet:

            path: /management/health/liveness

            port: 8081

            scheme: HTTPS

            httpHeaders:

            - name: Authorization

              value: "Basic ${BASE64_ACTUATOR_CREDS}"

          initialDelaySeconds: 60  # 应用启动时间

          periodSeconds: 30        # 检查间隔

          timeoutSeconds: 5        # 超时时间

          successThreshold: 1

          failureThreshold: 3      # 连续失败3次重启

        

        # 就绪探针(Readiness Probe)

        readinessProbe:

          httpGet:

            path: /management/health/readiness

            port: 8081

            scheme: HTTPS

            httpHeaders:

            - name: Authorization

              value: "Basic ${BASE64_ACTUATOR_CREDS}"

          initialDelaySeconds: 30

          periodSeconds: 15

          timeoutSeconds: 3

          successThreshold: 1

          failureThreshold: 3      # 连续失败3次标记为未就绪

        

        # 启动探针(Startup Probe)

        startupProbe:

          httpGet:

            path: /management/health/startup

            port: 8081

            scheme: HTTPS

          initialDelaySeconds: 5

          periodSeconds: 5

          timeoutSeconds: 2

          successThreshold: 1

          failureThreshold: 30     # 最长等待150秒启动

        

        # 资源限制

        resources:

          requests:

            memory: "512Mi"

            cpu: "250m"

          limits:

            memory: "1Gi"

            cpu: "500m"

        

        # 健康检查端口的安全上下文

        securityContext:

          readOnlyRootFilesystem: true

          allowPrivilegeEscalation: false

          capabilities:

            drop:

            - ALL

          runAsNonRoot: true

          runAsUser: 1000

```


## 自定义度量指标与告警


```java

// CustomMetrics.java - 自定义度量指标

package com.example.monitor.metrics;


import io.micrometer.core.instrument.*;

import io.micrometer.core.instrument.binder.BaseUnits;

import org.springframework.stereotype.Component;


import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.atomic.AtomicLong;

import java.util.concurrent.atomic.LongAdder;


@Component

public class CustomMetrics {

    

    private final MeterRegistry meterRegistry;

    private final ConcurrentHashMap requestTimers = new ConcurrentHashMap<>();

    private final ConcurrentHashMap errorCounters = new ConcurrentHashMap<>();

    private final LongAdder activeUsers = new LongAdder();

    private final AtomicLong cacheHitRatio = new AtomicLong(0);

    

    // Gauge指标

    private final Gauge userSessionGauge;

    private final Gauge orderQueueGauge;

    private final Gauge cacheEfficiencyGauge;

    

    // DistributionSummary

    private final DistributionSummary orderAmountSummary;

    private final DistributionSummary responseSizeSummary;

    

    // Timer

    private final Timer databaseQueryTimer;

    private final Timer externalApiTimer;

    

    public CustomMetrics(MeterRegistry meterRegistry) {

        this.meterRegistry = meterRegistry;

        

        // 初始化指标

        initializeMetrics();

    }

    

    private void initializeMetrics() {

        // 用户会话Gauge

        userSessionGauge = Gauge.builder("app.users.active", activeUsers, LongAdder::sum)

            .description("当前活跃用户数量")

            .baseUnit(BaseUnits.USERS)

            .tags("type", "session")

            .register(meterRegistry);

        

        // 订单队列Gauge

        orderQueueGauge = Gauge.builder("app.orders.queue.size", this::getOrderQueueSize)

            .description("待处理订单队列大小")

            .baseUnit(BaseUnits.ITEMS)

            .tags("type", "pending")

            .register(meterRegistry);

        

        // 缓存效率Gauge

        cacheEfficiencyGauge = Gauge.builder("app.cache.efficiency", cacheHitRatio, AtomicLong::get)

            .description("缓存命中率百分比")

            .baseUnit(BaseUnits.PERCENT)

            .register(meterRegistry);

        

        // 订单金额分布

        orderAmountSummary = DistributionSummary.builder("app.orders.amount")

            .description("订单金额分布")

            .baseUnit("CNY")

            .tags("currency", "CNY")

            .publishPercentiles(0.5, 0.95, 0.99)

            .publishPercentileHistogram()

            .register(meterRegistry);

        

        // 响应大小分布

        responseSizeSummary = DistributionSummary.builder("app.response.size")

            .description("HTTP响应大小分布")

            .baseUnit(BaseUnits.BYTES)

            .publishPercentiles(0.5, 0.95, 0.99)

            .register(meterRegistry);

        

        // 数据库查询计时器

        databaseQueryTimer = Timer.builder("app.database.query.time")

            .description("数据库查询执行时间")

            .publishPercentiles(0.5, 0.95, 0.99)

            .publishPercentileHistogram()

            .register(meterRegistry);

        

        // 外部API调用计时器

        externalApiTimer = Timer.builder("app.external.api.time")

            .description("外部API调用时间")

            .tags("type", "http")

            .publishPercentiles(0.5, 0.95, 0.99)

            .publishPercentileHistogram()

            .register(meterRegistry);

        

        // 自定义计数器

        Counter.builder("app.orders.created.total")

            .description("创建的订单总数")

            .tag("status", "created")

            .register(meterRegistry);

        

        Counter.builder("app.orders.completed.total")

            .description("完成的订单总数")

            .tag("status", "completed")

            .register(meterRegistry);

    }

    

    // 业务方法记录指标

    public void recordOrderCreation(double amount, String paymentMethod) {

        // 记录订单金额

        orderAmountSummary.record(amount);

        <"s3.p5k3.org.cn"><"f7.p5k3.org.cn"><"z9.p5k3.org.cn">

        // 递增订单计数器

        Counter counter = Counter.builder("app.orders.created")

            .tag("paymentMethod", paymentMethod)

            .register(meterRegistry);

        counter.increment();

        

        // 记录业务事件

        meterRegistry.counter("app.business.event", 

            "type", "order_created",

            "payment", paymentMethod

        ).increment();

    }

    

    public void recordDatabaseQuery(String queryType, long duration, TimeUnit unit) {

        Timer.Sample sample = Timer.start(meterRegistry);

        

        databaseQueryTimer.record(duration, unit);

        

        // 按查询类型分类记录

        Timer queryTimer = Timer.builder("app.database.query.type")

            .tag("query", queryType)

            .register(meterRegistry);

        queryTimer.record(duration, unit);

        

        sample.stop(Timer.builder("app.database.query.total")

            .register(meterRegistry));

    }

    

    public void recordApiCall(String endpoint, String method, long duration, TimeUnit unit, boolean success) {

        Timer.Sample sample = Timer.start(meterRegistry);

        

        // 记录API调用时间

        Timer endpointTimer = Timer.builder("app.api.endpoint.time")

            .tag("endpoint", endpoint)

            .tag("method", method)

            .tag("success", String.valueOf(success))

            .register(meterRegistry);

        endpointTimer.record(duration, unit);

        

        // 记录外部API调用

        externalApiTimer.record(duration, unit);

        

        // 记录成功/失败

        if (success) {

            meterRegistry.counter("app.api.call.success",

                "endpoint", endpoint,

                "method", method

            ).increment();

        } else {

            meterRegistry.counter("app.api.call.failure",

                "endpoint", endpoint,

                "method", method

            ).increment();

            

            // 记录错误详情

            recordError(endpoint, method);

        }

        

        sample.stop();

    }

    

    public void recordError(String component, String operation) {

        String key = component + ":" + operation;

        Counter counter = errorCounters.computeIfAbsent(key, k ->

            Counter.builder("app.errors.total")

                .tag("component", component)

                .tag("operation", operation)

                .register(meterRegistry)

        );

        counter.increment();

    }

    

    public void updateCacheMetrics(long hits, long misses) {

        long total = hits + misses;

        if (total > 0) {

            long ratio = (hits * 100) / total;

            cacheHitRatio.set(ratio);

        }

        

        // 更新缓存指标

        meterRegistry.gauge("app.cache.hits", hits);

        meterRegistry.gauge("app.cache.misses", misses);

        meterRegistry.gauge("app.cache.size", getCacheSize());

    }

    

    public void updateUserSession(boolean login) {

        if (login) {

            activeUsers.increment();

        } else {

            activeUsers.decrement();

        }

        

        // 记录用户活跃度

        meterRegistry.counter("app.user.session", 

            "action", login ? "login" : "logout"

        ).increment();

    }

    

    private long getOrderQueueSize() {

        // 从订单服务获取队列大小

        try {

            return orderService.getPendingOrderCount();

        } catch (Exception e) {

            return -1; // 表示未知

        }

    }

    

    private long getCacheSize() {

        // 获取缓存大小

        try {

            Cache cache = cacheManager.getCache("products");

            return cache != null ? cache.getSize() : 0;

        } catch (Exception e) {

            return -1;

        }

    }

}

```


基于Spring Boot Actuator的监控体系为企业级应用提供了全面的健康检查能力。通过自定义健康指示器、丰富的度量指标和Kubernetes探针集成,能够实时监控应用状态,及时发现并处理潜在问题。在实际生产环境中,需要结合具体业务场景设计监控指标,建立完整的告警和应急响应机制,确保系统的高可用性和稳定性。


请使用浏览器的分享功能分享到微信等