企业级应用:检测服务是否正常运行

1.说明:

在公司日常小项目中,会遇到一些小需求,比如:检测服务是否正常运行。

当一个经验不是很足的项目经理,让你写一个接口,然后检测服务是否正常运行啦。

然后你说阿里云有自动检测的接口,还能发短信到你手机上,他说不用。

你说可以用一个定时任务定时给服务发送请求,使用cron可以实现,他也说不用。

然后就用springcloud内部提供的健康监测接口吧,如下说明:

2.方式1:Ping(IP或者域名)

首先说明:使用ping来检测的话,会不可靠的。因为Ping可能会出现错误返回,而用http请求会准确很多

    public static void main(String[] args) {
        String ipAddress = "Recently.com"; // 替换为实际的服务IP地址

        try {
            InetAddress inetAddress = InetAddress.getByName(ipAddress);
            boolean isReachable = inetAddress.isReachable(5000); // 设置超时时间,单位为毫秒

            if (isReachable) {
                System.out.println("服务正常运行");
            } else {
                System.out.println("服务无法访问");
            }
        } catch (IOException e) {
            System.out.println("发生异常: " + e.getMessage());
        }
    }

部分字段说明:

InetAddress.isReachable() 方法用于检测主机的可达性,而不仅仅是服务的可达性。它通过发送一个特殊的ICMP Echo请求(类似于Ping请求)来测试目标主机是否可达。

然而,请注意,isReachable() 方法在不同的操作系统和网络配置下可能会有不同的行为。在某些情况下,由于操作系统或网络设备的限制,该方法可能会返回错误的结果或被阻塞。

此外,isReachable() 方法的实现也依赖于底层操作系统的特性。在某些操作系统上,可能需要具有管理员权限才能正确使用该方法。

因此,对于监测服务是否正常运行的目的,使用基于Ping的可达性测试并不是一种可靠的方法。更好的方法是通过与服务进行实际的通信,例如发送HTTP请求并检查响应状态码。

3.方式2:发送GET请求

1)ServiceMonitor 主类

使用HttpURLConnection发送HTTP GET请求到指定的服务URL,并根据响应代码判断服务是否正常。

public class ServiceMonitor {
    public static void main(String[] args) {
        String serviceUrl = "https://Recently.com:9091/actuator/health";
        Boolean flag =true;
        while (flag){
            try {
                URL url = new URL(serviceUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(5000); // 设置连接超时时间,单位为毫秒
                connection.setReadTimeout(5000); // 设置读取超时时间,单位为毫秒

                int responseCode = connection.getResponseCode();

                 if (responseCode == HttpURLConnection.HTTP_OK) {
                    System.out.println("服务正常运行");
                } else {
                    System.out.println("服务无法访问,响应代码: " + responseCode);
                    // 获取错误信息
                    String errorResponse = getErrorResponse(connection);
                    System.out.println("错误响应内容: " + errorResponse);
                    flag = false;
                }
                Thread.sleep(5000);
            } catch (IOException e) {
                System.out.println("发生异常: " + e.getMessage());
                flag=false;
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }

 // 获取错误响应内容
    private static String getErrorResponse(HttpURLConnection connection) throws IOException {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            return response.toString();
        }
}

这里需要说明一下,SpringBoot项目中是可以存在非入口类main方法的,也就是说非入口类main方法跟入口类main方法可以同时存在项目中,处理不一样的逻辑内容。

代码中的ServiceMonitor类包含一个main方法,用于执行服务监测逻辑。它通过创建URL对象和HttpURLConnection对象来与服务进行通信,并设置连接和读取超时时间。然后,通过调用connection.getResponseCode()方法获取响应代码,根据响应代码判断服务的健康状态。

如果响应代码为HTTP_OK,表示服务正常运行,输出"服务正常运行"。否则,输出"服务无法访问"以及响应代码,并调用getErrorResponse()方法获取错误响应内容并输出。

getErrorResponse()方法中,它通过读取错误流并将内容存储在字符串中,最后返回错误响应内容。

2)DataSourceConfig 获取配置文件中的数据库信息

@Data
@Component
@ConfigurationProperties(prefix = "global.datasource")
public class DataSourceConfig {
    private String url;
    private String username;
    private String password;
}

 在应用启动时,Spring容器会读取配置文件中的属性值,并将其绑定到DataSourceConfig类的对应属性上,可以通过注入DataSourceConfig类的实例来访问这些属性的值。关于Spring容器会读取配置文件中的属性值的详细说明,在我的另一篇文章中有详细说明:SpringBoot中YML,yaml,properties文件的读取_Recently 祝祝的博客-CSDN博客SpringBoot中YML,yaml,properties文件的读取https://blog.csdn.net/qq_45656077/article/details/129013297?spm=1001.2014.3001.5501 

3)HealthCheckController 健康检测主要实现类

@Controller
@RequestMapping("/actuator")
public class HealthCheckController implements HealthIndicator {

    @Autowired
    private DataSourceConfig dataSourceConfig;

    @Override
    public Health health() {
        boolean isHealthy = checkHealth(); // 根据实际需求进行健康状态检查

        if (isHealthy) {
            return Health.up().build();
        } else {
            return Health.down().build();
        }
    }

    @GetMapping("/health")
    public String getHealthStatus() {
        Health health = health();
        return health.getStatus().getCode(); // 返回健康状态码
    }

    private boolean checkHealth() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(dataSourceConfig.getUrl(),
                    dataSourceConfig.getUsername(), dataSourceConfig.getPassword());
            connection.close();
            return true;
        } catch (SQLException e) {
            return false;
        }
    }
}

实现了HealthIndicator接口,该接口定义了一个health()方法,用于返回应用程序的健康状态。在实现中,它调用了checkHealth()方法进行实际的健康状态检查。

如果健康检查结果为true,即服务健康,则通过Health.up().build()方法返回一个UP状态的Health对象。

如果健康检查结果为false,即服务不健康,则通过Health.down().build()方法返回一个DOWN状态的Health对象。

另外,该类还定义了一个getHealthStatus()方法,用于处理"/actuator/health"路径的GET请求,并返回健康状态码。它内部调用了health()方法来获取健康状态,并通过health.getStatus().getCode()方法获取健康状态码并返回。

checkHealth()方法中,它通过使用DriverManagerDataSourceConfig中的数据库连接属性来尝试建立数据库连接。如果连接成功,表示数据库可用,返回true,否则表示数据库不可用,返回false

4.总结说明

上边我的示例是通过检测数据库时候能够连接成功,并且通过HTTP请求接口服务,来检测服务是否正常,其实还可以通过外部服务依赖检查、磁盘空间检查、内存利用率检查、CPU利用率检查、日志检查、健康指标检查来查看服务健康状态,只有需要在接口checkHealth()方法中添加逻辑即可。

checkHealth()方法根据实际需求编写健康状态检查的逻辑 、以检查数据库连接、外部依赖、服务可用性等 、返回true表示健康,返回false表示不健康

 

你可能感兴趣的:(Java,java,服务器,开发语言)