From 78ca251e964b92003209799f9a0da704f605172d Mon Sep 17 00:00:00 2001 From: joyita07 Date: Fri, 30 Oct 2020 06:36:13 -0700 Subject: [PATCH] Added support for ReactiveHealthIndicator. (#3903) --- .../eureka/EurekaHealthCheckHandler.java | 38 +++++++-- .../eureka/EurekaHealthCheckHandlerTests.java | 80 ++++++++++++++++--- 2 files changed, 101 insertions(+), 17 deletions(-) diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandler.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandler.java index ff815f643..bff747809 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandler.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandler.java @@ -17,12 +17,14 @@ package org.springframework.cloud.netflix.eureka; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import com.netflix.appinfo.HealthCheckHandler; import com.netflix.appinfo.InstanceInfo; +import com.netflix.appinfo.InstanceInfo.InstanceStatus; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; @@ -32,6 +34,7 @@ import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthAggregator; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.HealthIndicatorRegistryFactory; +import org.springframework.boot.actuate.health.ReactiveHealthIndicator; import org.springframework.boot.actuate.health.Status; import org.springframework.boot.actuate.health.StatusAggregator; import org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthContributor; @@ -40,8 +43,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.util.Assert; -import static com.netflix.appinfo.InstanceInfo.InstanceStatus; - /** * A Eureka health checker, maps the application status into {@link InstanceStatus} that * will be propagated to Eureka registry. @@ -52,6 +53,7 @@ import static com.netflix.appinfo.InstanceInfo.InstanceStatus; * * @author Jakub Narloch * @author Spencer Gibb + * @author Nowrin Anwar Joyita * @see HealthCheckHandler * @see StatusAggregator * @see HealthAggregator @@ -74,6 +76,8 @@ public class EurekaHealthCheckHandler private Map healthIndicators; + private Map reactiveHealthIndicators = new HashMap<>(); + @Deprecated private CompositeHealthIndicator healthIndicator; @@ -110,8 +114,12 @@ public class EurekaHealthCheckHandler .getBeansOfType(HealthIndicator.class); this.healthIndicators = new HashMap<>(); + final Map reactiveHealthIndicators = applicationContext + .getBeansOfType(ReactiveHealthIndicator.class); + if (statusAggregator != null) { populateHealthIndicators(healthIndicators); + populateReactiveHealthIndicators(reactiveHealthIndicators); } else { createHealthIndicator(healthIndicators); @@ -165,6 +173,14 @@ public class EurekaHealthCheckHandler } } + void populateReactiveHealthIndicators( + Map reactiveHealthIndicators) { + for (Map.Entry entry : reactiveHealthIndicators + .entrySet()) { + this.reactiveHealthIndicators.put(entry.getKey(), entry.getValue()); + } + } + @Override public InstanceStatus getStatus(InstanceStatus instanceStatus) { return getHealthStatus(); @@ -190,9 +206,21 @@ public class EurekaHealthCheckHandler protected Status getStatus(StatusAggregator statusAggregator) { Status status; - Set statusSet = healthIndicators.values().stream() - .map(HealthIndicator::health).map(Health::getStatus) - .collect(Collectors.toSet()); + + Set statusSet = new HashSet<>(); + if (healthIndicators != null) { + statusSet.addAll( + healthIndicators.values().stream().map(HealthIndicator::health) + .map(Health::getStatus).collect(Collectors.toSet())); + } + + if (reactiveHealthIndicators != null) { + statusSet.addAll(reactiveHealthIndicators.values().stream() + .map(ReactiveHealthIndicator::health).map(health -> { + return health.block().getStatus(); + }).collect(Collectors.toSet())); + } + status = statusAggregator.getAggregateStatus(statusSet); return status; } diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandlerTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandlerTests.java index 1b29bf3f0..a9dabb443 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandlerTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandlerTests.java @@ -21,11 +21,15 @@ import java.util.List; import com.netflix.appinfo.InstanceInfo.InstanceStatus; import org.junit.Before; import org.junit.Test; +import reactor.core.publisher.Mono; import org.springframework.boot.actuate.health.AbstractHealthIndicator; +import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.OrderedHealthAggregator; +import org.springframework.boot.actuate.health.ReactiveHealthIndicator; +import org.springframework.boot.actuate.health.SimpleStatusAggregator; import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicator; import org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthIndicator; import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator; @@ -39,27 +43,29 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests the {@link EurekaHealthCheckHandler} with different health indicator registered. * * @author Jakub Narloch + * @author Nowrin Anwar Joyita */ public class EurekaHealthCheckHandlerTests { private EurekaHealthCheckHandler healthCheckHandler; + private EurekaHealthCheckHandler healthCheckHandlerWithStatusAggregator; @Before public void setUp() throws Exception { - - healthCheckHandler = new EurekaHealthCheckHandler(new OrderedHealthAggregator()); + healthCheckHandler = new EurekaHealthCheckHandler( + new OrderedHealthAggregator()); + healthCheckHandlerWithStatusAggregator = new EurekaHealthCheckHandler( + new SimpleStatusAggregator()); } @Test public void testNoHealthCheckRegistered() throws Exception { - InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UNKNOWN); assertThat(status).isEqualTo(InstanceStatus.UNKNOWN); } @Test public void testAllUp() throws Exception { - initialize(UpHealthConfiguration.class); InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UNKNOWN); @@ -67,8 +73,7 @@ public class EurekaHealthCheckHandlerTests { } @Test - public void testDown() throws Exception { - + public void testDownWithBlockingIndicators() throws Exception { initialize(UpHealthConfiguration.class, DownHealthConfiguration.class); InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UNKNOWN); @@ -76,8 +81,35 @@ public class EurekaHealthCheckHandlerTests { } @Test - public void testUnknown() throws Exception { + public void testDownWithReactiveIndicators() throws Exception { + initialize(ReactiveUpHealthConfiguration.class, + ReactiveDownHealthConfiguration.class); + InstanceStatus status = healthCheckHandlerWithStatusAggregator + .getStatus(InstanceStatus.UNKNOWN); + assertThat(status).isEqualTo(InstanceStatus.DOWN); + } + + @Test + public void testDownWhenBlockingIndicatorUpAndReactiveDown() throws Exception { + initialize(UpHealthConfiguration.class, ReactiveDownHealthConfiguration.class); + + InstanceStatus status = healthCheckHandlerWithStatusAggregator + .getStatus(InstanceStatus.UNKNOWN); + assertThat(status).isEqualTo(InstanceStatus.DOWN); + } + + @Test + public void testDownWhenBlockingIndicatorDownAndReactiveUp() throws Exception { + initialize(DownHealthConfiguration.class, ReactiveUpHealthConfiguration.class); + + InstanceStatus status = healthCheckHandlerWithStatusAggregator + .getStatus(InstanceStatus.UNKNOWN); + assertThat(status).isEqualTo(InstanceStatus.DOWN); + } + + @Test + public void testUnknown() throws Exception { initialize(FatalHealthConfiguration.class); InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UNKNOWN); @@ -86,7 +118,6 @@ public class EurekaHealthCheckHandlerTests { @Test public void testEurekaIgnored() throws Exception { - initialize(EurekaDownHealthConfiguration.class); InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UP); @@ -98,10 +129,12 @@ public class EurekaHealthCheckHandlerTests { configurations); healthCheckHandler.setApplicationContext(applicationContext); healthCheckHandler.afterPropertiesSet(); + healthCheckHandlerWithStatusAggregator + .setApplicationContext(applicationContext); + healthCheckHandlerWithStatusAggregator.afterPropertiesSet(); } public static class UpHealthConfiguration { - @Bean public HealthIndicator healthIndicator() { return new AbstractHealthIndicator() { @@ -115,7 +148,6 @@ public class EurekaHealthCheckHandlerTests { } public static class DownHealthConfiguration { - @Bean public HealthIndicator healthIndicator() { return new AbstractHealthIndicator() { @@ -129,7 +161,6 @@ public class EurekaHealthCheckHandlerTests { } public static class FatalHealthConfiguration { - @Bean public HealthIndicator healthIndicator() { return new AbstractHealthIndicator() { @@ -142,8 +173,33 @@ public class EurekaHealthCheckHandlerTests { } - public static class EurekaDownHealthConfiguration { + public static class ReactiveUpHealthConfiguration { + @Bean + public ReactiveHealthIndicator reactiveHealthIndicator() { + return new AbstractReactiveHealthIndicator() { + @Override + protected Mono doHealthCheck(Health.Builder builder) { + return Mono.just(builder.up().build()); + } + }; + } + } + + public static class ReactiveDownHealthConfiguration { + @Bean + public ReactiveHealthIndicator reactiveHealthIndicator() { + return new AbstractReactiveHealthIndicator() { + @Override + protected Mono doHealthCheck(Health.Builder builder) { + return Mono.just(builder.down().build()); + } + }; + } + + } + + public static class EurekaDownHealthConfiguration { @Bean public DiscoveryHealthIndicator discoveryHealthIndicator() { return new DiscoveryClientHealthIndicator(null, null) {