以编程方式将健康指标添加到Springboot执行器组



问题

我想以编程方式将健康指标包括在执行器组中。他们现在唯一能做到这一点的方法是在*.properties文件中。

用例

根据在应用程序中找到的bean或其他属性,最好自动或手动将Health Indicators添加到就绪/活跃组中。虽然设置房产似乎很容易,但在许多情况下,开发商可能会忘记设置,或者有些旧项目人们不知道可能需要配置哪些健康指标。

示例:

如果在应用程序中启用了数据源健康指示器,那么将该健康指示器自动配置到就绪组中会很好。但是,如果数据源运行状况指示器未处于活动状态,我们就不希望出现这种情况。

谢谢!

您需要添加HealthIndicator bean来实现自定义健康指标,然后需要注入CustomHealthIndicater。

步骤1:在应用程序中创建自定义运行状况指示器

import com.google.common.collect.ImmutableMap;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.actuate.health.CompositeHealthIndicator;
import org.springframework.boot.actuate.health.HealthAggregator;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
import java.util.Map;
/**
 * Update #getStatus() to do your detailed application check (testing for databases, external services, queues, etc.)
 * to represent your health check by indicating all its components are also functional (as opposed to a simple
 * application-is-running check).
 */
public class EurekaHealthCheckHandler implements HealthCheckHandler, ApplicationContextAware, InitializingBean {
    public final static ImmutableMap<Status, InstanceInfo.InstanceStatus> healthStatuses =
            new ImmutableMap.Builder<Status, InstanceInfo.InstanceStatus>()
                    .put(Status.UNKNOWN, InstanceInfo.InstanceStatus.UNKNOWN)
                    .put(Status.OUT_OF_SERVICE, InstanceInfo.InstanceStatus.OUT_OF_SERVICE)
                    .put(Status.DOWN, InstanceInfo.InstanceStatus.DOWN)
                    .put(Status.UP, InstanceInfo.InstanceStatus.UP)
                    .build();
    private final CompositeHealthIndicator healthIndicator;
    private ApplicationContext applicationContext;
    public EurekaHealthCheckHandler(HealthAggregator healthAggregator) {
        Assert.notNull(healthAggregator, "HealthAggregator must not be null");
        this.healthIndicator = new CompositeHealthIndicator(healthAggregator);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        final Map<String, HealthIndicator> healthIndicators = applicationContext.getBeansOfType(HealthIndicator.class);
        for (Map.Entry<String, HealthIndicator> entry : healthIndicators.entrySet()) {
            healthIndicator.addHealthIndicator(entry.getKey(), entry.getValue());
        }
    }
    @Override
    public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus instanceStatus) {
        Status status = healthIndicator.health().getStatus();
        return healthStatuses.containsKey(status) ? healthStatuses.get(status) : InstanceInfo.InstanceStatus.UNKNOWN;
    }
}

然后根据您的需求实施健康指标

import lombok.extern.slf4j.Slf4j;
import com.application.services.SmsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
/**
 * Spring Cloud Health Indicator (for Eureka discovery). Sends a ping to Twilio and if sent successfully reports
 * service as UP otherwise DOWN.
 */
@Component
@Slf4j
public class SmsHealthIndicator implements HealthIndicator {
    @Autowired
    private SmsService smsService;
    /**
     * Performs health check by getting first SMS from Twilio.
     */
    @Override
    public Health health() {
        try {
            smsService.testSampleMessage();
            return Health.up().build();
        } catch (Exception e) {
            log.error("HealthCheck with Twilio failed", e);
            return Health.down(e).build();
        }
    }
}

这应该满足您的要求

我想我能想到的就是zlsmith86已经提出的建议。基本上,我从我可能需要的所有HealthIndicatorHealthContributor bean中创建了一个名为readinessProbe的自定义CompositeHealthContributor bean,注入为Optional,并包含在复合贡献器中(如果存在的话(。然后,management.endpoint.health.group.readiness.include配置的值可以始终设置为readinessProbe,即自定义复合健康贡献者bean的名称。

自定义复合健康贡献者:

package io.github.devatherock.config;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.actuate.health.CompositeHealthContributor;
import org.springframework.boot.actuate.health.HealthContributor;
import org.springframework.boot.actuate.system.DiskSpaceHealthIndicator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ReadinessProbeConfig {
    @Bean
    public CompositeHealthContributor readinessProbe(
            @Qualifier("dbHealthContributor") Optional<HealthContributor> dbHealthContributor,
            @Qualifier("mongoHealthContributor") Optional<HealthContributor> mongoHealthContributor,
            Optional<DiskSpaceHealthIndicator> diskSpaceHealthIndicator) {
        Map<String, HealthContributor> healthIndicatorMap = Arrays
                .asList(dbHealthContributor, mongoHealthContributor, diskSpaceHealthIndicator)
                .stream()
                .filter(Optional::isPresent)
                .collect(Collectors.toMap(
                        indicator -> indicator.get().getClass().getSimpleName(), Optional::get));
        return CompositeHealthContributor.fromMap(healthIndicatorMap);
    }
}

应用程序.yml:

management:
  endpoint:
    health:
      probes:
        enabled: true
      group:
        readiness:
          include: readinessProbe 

最新更新