免责声明
本文代表了我对该解决方案的看法,因此,任何建议,修复或讨论都将受到高度赞赏。
短篇小说
在当今复杂的软件景观中,了解应用程序的健康状况从未如此重要。应用程序的“健康”超出了正常运行时间。它涉及应用程序与其所依赖的外部资源有效交互的能力,例如数据库,API或缓存。
我们广泛使用Spring Boot应用程序,这些应用程序很大程度上取决于定制API,第三方API和内部caches等各种外部数据源。主要目的是确保这些应用程序在Kubernetes部署中的健康状况。
每个应用程序都有自己独特的健康状态,取决于其使用的外部资源的状态。例如,如果您的应用程序与第三方服务或数据库进行通信,则其健康状况不仅依赖于其内部功能,还依赖于这些外部系统的可用性和响应性。
如果必需的外部来源经历停机时间,即使应用程序本身运行完美,它也可能会严重影响我们的应用程序的性能和业务逻辑。因此,在确定应用程序的健康状况时要考虑这些外部因素至关重要。
健康检查为这一挑战提供了解决方案。它们允许您监视和评估您应用程序所依赖的系统的状态。如果外部来源对于您的应用程序很重要,则需要将其包括在健康检查中。
例如,如果您的应用程序在很大程度上依赖于特定的API,则应实现确保API启动并运行的健康检查。这样,如果有问题,您将被提醒,并且您可以及时解决它,以防止对您的申请产生任何严重后果。
Spring Boot的健康指标
Spring Boot提供了一个重要的功能,可以帮助您进行自定义的健康指标。 HealthIndicator
接口提供了一种方法health()
,可以返回健康响应。您可以根据应用程序的要求定义健康规则,范围从检查数据库连接到验证外部服务的状态。
使用Spring Boot,您可以根据自己的特定需求自定义这些健康指标,以确保应用程序健康状况的准确性。例如,如果您的应用程序使用外部API和一个缓存系统,则可以为API创建两个独立的健康指标,另一个用于缓存。如果两个系统遇到问题,相关的健康指标将报告,使您能够及时采取行动。
实施
让我们配置两种健康指标:
- 对于外部API
- 用于内部缓存
外部API的健康指标
我们的自定义ApiHealthIndicator
接口为我们要通过提供doHealthCheck()
方法来监视的所有外部API创建合同。默认情况下,我们将通过此接口的默认方法来创建健康状况:健康状态和一个不健康的状态。
您可以在down
健康状态中添加其他详细信息,例如自定义运行时异常,详细消息等。
import org.springframework.boot.actuate.health.Health;
import reactor.core.publisher.Mono;
import static org.apache.commons.lang3.BooleanUtils.isFalse;
import static org.apache.commons.lang3.BooleanUtils.isTrue;
public interface ApiHealthIndicator {
Mono<Health> doHealthCheck();
default Health createHealth(Boolean status, String serviceName) {
return isTrue(status)
? new Health.Builder().up().build()
: createHealthDownStatus(status, serviceName);
}
default Health createHealthDownStatus(String serviceName) {
var exception = new ServiceUnavailableException(String.format("The %s isn't available", serviceName));
return new Health.Builder()
.down(exception)
.build();
}
}
组件ServiceStateHealthIndicator
有效地执行了所需的逻辑:它集成了从外部API检索当前状态的服务bean,表明API是否可用或不可用(true/false)。当监视资源(例如Kubernetes)通过执行器向应用程序的HealthEndpoint
发送健康检查请求时,getHealth()
方法会触发。此方法提供了所有HealthContributor
实例的状态,其中包括我们的自定义ReactiveHealthIndicator
。
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
public class ServiceStateHealthIndicator implements ReactiveHealthIndicator, ApiHealthIndicator {
private static final String SERVICE_NAME = "external-api";
private final ApiService service;
public ServiceStateHealthIndicator(ApiService service) {
this.service = service;
}
@Override
public Mono<Health> health() {
return doHealthCheck()
.onErrorResume(exception -> Mono.just(createHealthDownStatus(false, SERVICE_NAME)));
}
@Override
public Mono<Health> doHealthCheck() {
return service.getStatus()
.map(status -> createHealth(status, SERVICE_NAME));
}
}
当然,我们的自定义例外是解释其反映的状态:
public class ServiceUnavailableException extends RuntimeException {
public ServiceUnavailableException(String message) {
super(message);
}
}
内部缓存的健康指标
假设我们应用程序的健康先决条件之一是存在内部缓存。如果缓存为空,我们希望防止应用程序完全启动。为了促进这一点,我们可以使用Spring Boot的ReadinessState.class
来调整准备状态以控制可用性状态。
假设我们有一个接口CacheService
,它提供了与我们内部缓存相关的每个类中实现的isNotEmpty()
方法。此方法可提供直接的布尔结果,使我们能够验证我们的每个内部缓存是否处于有效状态。
通过注入包含所有缓存服务豆的地图,我们可以循环浏览每个缓存。如果即使是单个缓存为空,则准备状态会阻止任何流量到达应用程序。
我们可以在Spring引导中扩展AvailabilityStateHealthIndicator
,以创建状态的映射并调整getState()
方法。此方法基于我们的caches状态产生ReadinessState
的实例。
当kubernetes等外部监视工具(例如,将HTTP请求发送到我们应用程序的准备就绪终点)时
import org.springframework.boot.actuate.availability.AvailabilityStateHealthIndicator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.availability.ApplicationAvailability;
import org.springframework.boot.availability.AvailabilityState;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class CacheStateHealthIndicator extends AvailabilityStateHealthIndicator {
private final Map<String, CacheService> cacheServices;
public CacheStateHealthIndicator(Map<String, CacheService> cacheServices, ApplicationAvailability availability) {
super(availability, ReadinessState.class, statusMappings -> {
statusMappings.add(ReadinessState.ACCEPTING_TRAFFIC, Status.UP);
statusMappings.add(ReadinessState.REFUSING_TRAFFIC, Status.OUT_OF_SERVICE);
});
this.cacheServices = cacheServices;
}
@Override
protected AvailabilityState getState(ApplicationAvailability applicationAvailability) {
boolean isEmpty = cacheServices.values()
.stream()
.map(CacheService::isNotEmpty)
.toList()
.contains(false);
if (isEmpty) return ReadinessState.REFUSING_TRAFFIC;
return ReadinessState.ACCEPTING_TRAFFIC;
}
}
概括
总而言之,Spring Boot提供了一个全面且可自定义的系统,用于监视应用程序的健康状况。它的HealthIndicator
接口使您可以考虑确定应用程序的健康状况时的所有关键因素,包括基本外部来源。此功能有助于防止小问题升级为重大问题,增强您的应用程序的可靠性。
在下一篇文章中,我将展示我们如何使用这些自定义的健康指标来实现application.properties
文件中的kubernetes探针。