# 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
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
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
"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
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
"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
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
// 分析各个组件的状态
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
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
private final 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探针集成,能够实时监控应用状态,及时发现并处理潜在问题。在实际生产环境中,需要结合具体业务场景设计监控指标,建立完整的告警和应急响应机制,确保系统的高可用性和稳定性。