Java健康检查案例

wen java案例 1

本文目录导读:

Java健康检查案例

  1. 基础健康检查(使用Spring Boot Actuator)
  2. 自定义健康检查服务
  3. RESTful健康检查接口
  4. Docker健康检查配置
  5. 配置文件
  6. 健康检查工具类
  7. 使用示例

我来为您提供一个完整的Java健康检查案例,包含多种实现方式。

基础健康检查(使用Spring Boot Actuator)

Maven依赖

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

配置文件 application.yml

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
  endpoint:
    health:
      show-details: always
      probes:
        enabled: true
  health:
    db:
      enabled: true
    redis:
      enabled: true

自定义健康检查指示器

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
    @Override
    public Health health() {
        try {
            // 模拟数据库健康检查
            boolean isDatabaseUp = checkDatabaseConnection();
            if (isDatabaseUp) {
                return Health.up()
                    .withDetail("database", "MySQL")
                    .withDetail("status", "connected")
                    .build();
            } else {
                return Health.down()
                    .withDetail("database", "MySQL")
                    .withDetail("status", "disconnected")
                    .build();
            }
        } catch (Exception e) {
            return Health.down(e)
                .withDetail("error", e.getMessage())
                .build();
        }
    }
    private boolean checkDatabaseConnection() {
        // 实际的数据库连接检查逻辑
        return true;
    }
}

自定义服务健康检查

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import java.net.HttpURLConnection;
import java.net.URL;
@Component
public class ExternalServiceHealthIndicator implements HealthIndicator {
    @Override
    public Health health() {
        try {
            URL url = new URL("https://api.example.com/health");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(3000);
            connection.setRequestMethod("GET");
            int responseCode = connection.getResponseCode();
            if (responseCode == 200) {
                return Health.up()
                    .withDetail("service", "External API")
                    .withDetail("responseCode", responseCode)
                    .build();
            } else {
                return Health.down()
                    .withDetail("service", "External API")
                    .withDetail("responseCode", responseCode)
                    .build();
            }
        } catch (Exception e) {
            return Health.down(e)
                .withDetail("service", "External API")
                .withDetail("error", e.getMessage())
                .build();
        }
    }
}

自定义健康检查服务

健康检查核心服务

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HealthCheckService {
    private static final Logger logger = LoggerFactory.getLogger(HealthCheckService.class);
    private final Map<String, HealthStatus> healthStatusMap = new ConcurrentHashMap<>();
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
    // 健康状态枚举
    public enum HealthStatus {
        UP, DOWN, DEGRADED, UNKNOWN
    }
    // 健康检查结果类
    public static class HealthResult {
        private final HealthStatus status;
        private final Map<String, Object> details;
        private final long timestamp;
        public HealthResult(HealthStatus status, Map<String, Object> details) {
            this.status = status;
            this.details = details;
            this.timestamp = System.currentTimeMillis();
        }
        public HealthStatus getStatus() {
            return status;
        }
        public Map<String, Object> getDetails() {
            return details;
        }
        public long getTimestamp() {
            return timestamp;
        }
    }
    // 注册健康检查器
    public void registerChecker(String name, Checkable checker) {
        healthStatusMap.put(name, HealthStatus.UNKNOWN);
        scheduler.scheduleAtFixedRate(() -> {
            HealthResult result = performCheck(name, checker);
            updateHealthStatus(name, result);
        }, 0, 30, TimeUnit.SECONDS);  // 每30秒执行一次
    }
    // 执行健康检查
    private HealthResult performCheck(String name, Checkable checker) {
        try {
            checker.check();
            return new HealthResult(HealthStatus.UP, Map.of("lastCheck", System.currentTimeMillis()));
        } catch (Exception e) {
            logger.error("Health check failed for: {}", name, e);
            return new HealthResult(HealthStatus.DOWN, 
                Map.of("error", e.getMessage(), "lastCheck", System.currentTimeMillis()));
        }
    }
    // 更新健康状态
    private void updateHealthStatus(String name, HealthResult result) {
        healthStatusMap.put(name, result.getStatus());
        if (result.getStatus() == HealthStatus.DOWN) {
            // 发送告警通知
            sendAlert(name, result);
        }
    }
    // 获取所有健康状态
    public Map<String, HealthStatus> getAllHealthStatus() {
        return new ConcurrentHashMap<>(healthStatusMap);
    }
    // 获取特定服务健康状态
    public HealthStatus getHealthStatus(String serviceName) {
        return healthStatusMap.getOrDefault(serviceName, HealthStatus.UNKNOWN);
    }
    // 查询整体健康状态
    public boolean isSystemHealthy() {
        return !healthStatusMap.containsValue(HealthStatus.DOWN);
    }
    // 发送告警
    private void sendAlert(String serviceName, HealthResult result) {
        // 实现邮件、短信、Webhook等告警通知
        logger.warn("Service {} is down: {}", serviceName, result.getDetails());
    }
    // 关闭资源
    public void shutdown() {
        scheduler.shutdown();
    }
    // 健康检查接口
    public interface Checkable {
        void check() throws Exception;
    }
}

具体健康检查实现

// 数据库健康检查
@Component
public class DatabaseHealthChecker implements HealthCheckService.Checkable {
    @Autowired
    private DataSource dataSource;
    @Override
    public void check() throws Exception {
        try (Connection conn = dataSource.getConnection()) {
            if (conn.isValid(5)) {
                return;
            }
            throw new Exception("Database connection is invalid");
        }
    }
}
// Redis健康检查
@Component
public class RedisHealthChecker implements HealthCheckService.Checkable {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Override
    public void check() throws Exception {
        try {
            String result = redisTemplate.opsForValue().get("health_check_key");
            // 可以执行PING命令验证Redis连接
            if (result == null) {
                redisTemplate.opsForValue().set("health_check_key", "ok", Duration.ofSeconds(10));
            }
        } catch (Exception e) {
            throw new Exception("Redis connection failed", e);
        }
    }
}
// 磁盘空间检查
@Component
public class DiskSpaceHealthChecker implements HealthCheckService.Checkable {
    @Override
    public void check() throws Exception {
        File root = new File("/");
        long freeSpace = root.getUsableSpace();
        long totalSpace = root.getTotalSpace();
        double usageRatio = 1.0 - (double) freeSpace / totalSpace;
        if (usageRatio > 0.9) {
            throw new Exception("Disk usage > 90%");
        }
    }
}
// 内存使用检查
@Component
public class MemoryHealthChecker implements HealthCheckService.Checkable {
    @Override
    public void check() throws Exception {
        Runtime runtime = Runtime.getRuntime();
        long maxMemory = runtime.maxMemory();
        long usedMemory = runtime.totalMemory() - runtime.freeMemory();
        double memoryUsage = (double) usedMemory / maxMemory;
        if (memoryUsage > 0.85) {
            throw new Exception("Memory usage > 85%");
        }
    }
}

RESTful健康检查接口

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/health")
public class HealthController {
    @Autowired
    private HealthCheckService healthCheckService;
    @GetMapping("/check")
    public Map<String, Object> checkHealth() {
        Map<String, Object> result = new HashMap<>();
        result.put("status", healthCheckService.isSystemHealthy() ? "UP" : "DOWN");
        result.put("services", healthCheckService.getAllHealthStatus());
        result.put("timestamp", System.currentTimeMillis());
        return result;
    }
    @GetMapping("/service/{name}")
    public Map<String, Object> checkServiceHealth(@PathVariable String name) {
        Map<String, Object> result = new HashMap<>();
        result.put("service", name);
        result.put("status", healthCheckService.getHealthStatus(name));
        result.put("timestamp", System.currentTimeMillis());
        return result;
    }
}

Docker健康检查配置

FROM openjdk:11-jre-slim
COPY target/app.jar app.jar
# Dockerfile中使用HEALTHCHECK指令
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s \
  CMD curl -f http://localhost:8080/api/health/check || exit 1
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

配置文件

server:
  port: 8080
app:
  health-check:
    enabled: true      # 是否启用健康检查
    interval: 30      # 检查间隔(秒)
    timeout: 5        # 超时时间(秒)
    alert-enabled: true  # 是否启用告警
    alert-webhook: "https://hooks.example.com/alerts"

健康检查工具类

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
public class JVMHealthUtils {
    public static Map<String, Object> getJVMStats() {
        Map<String, Object> stats = new HashMap<>();
        // 内存统计
        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
        stats.put("heap_used", formatBytes(memoryMXBean.getHeapMemoryUsage().getUsed()));
        stats.put("heap_max", formatBytes(memoryMXBean.getHeapMemoryUsage().getMax()));
        stats.put("non_heap_used", formatBytes(memoryMXBean.getNonHeapMemoryUsage().getUsed()));
        // CPU使用
        OperatingSystemMXBean osMXBean = ManagementFactory.getOperatingSystemMXBean();
        stats.put("cpu_cores", osMXBean.getAvailableProcessors());
        stats.put("system_load_average", osMXBean.getSystemLoadAverage());
        // 线程统计
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        stats.put("thread_count", threadMXBean.getThreadCount());
        stats.put("daemon_thread_count", threadMXBean.getDaemonThreadCount());
        stats.put("peak_thread_count", threadMXBean.getPeakThreadCount());
        stats.put("total_started_thread_count", threadMXBean.getTotalStartedThreadCount());
        // JVM信息
        Runtime runtime = Runtime.getRuntime();
        stats.put("total_memory", formatBytes(runtime.totalMemory()));
        stats.put("free_memory", formatBytes(runtime.freeMemory()));
        stats.put("used_memory", formatBytes(runtime.totalMemory() - runtime.freeMemory()));
        return stats;
    }
    private static String formatBytes(long bytes) {
        if (bytes < 1024) return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(1024));
        String pre = "KMGTPE".charAt(exp - 1) + "B";
        return String.format("%.1f %s", bytes / Math.pow(1024, exp), pre);
    }
}

使用示例

@Component
public class HealthCheckDemo {
    @Autowired
    private HealthCheckService healthCheckService;
    @Autowired
    private DatabaseHealthChecker databaseHealthChecker;
    @Autowired
    private RedisHealthChecker redisHealthChecker;
    @PostConstruct
    public void init() {
        // 注册健康检查器
        healthCheckService.registerChecker("database", databaseHealthChecker);
        healthCheckService.registerChecker("redis", redisHealthChecker);
        healthCheckService.registerChecker("disk", new DiskSpaceHealthChecker());
    }
}

这个完整的健康检查案例包括了:

  1. Spring Boot Actuator 集成的健康检查
  2. 自定义健康检查服务,支持定时检查和多种检查器
  3. RESTful API 暴露健康检查接口
  4. Docker 健康检查配置
  5. JVM 统计工具类
  6. 丰富的健康指标:数据库、Redis、磁盘、内存、CPU等

可根据实际需求选择合适的实现方式。

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