diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index d078f0e36..4b61bce78 100755 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -324,6 +324,13 @@ eureka.instance.metadataMap.zone = zone2 eureka.client.preferSameZoneEureka = true ``` +=== Refreshing Eureka Clients + +By default, the `EurekaClient` bean is refreshable, meaning the Eureka client properties can be changed and refreshed. +When a refresh occurs clients will be unregistered from the Eureka server and there might be a brief moment of time +where all instance of a given service are not available. One way to eliminate this from happening is to disable +the ability to refresh Eureka clients. To do this set `eureka.client.refresh.enable=false`. + [[spring-cloud-eureka-server]] == Service Discovery: Eureka Server diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java index f26a65820..992dca2b3 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java @@ -370,6 +370,7 @@ public class EurekaClientAutoConfiguration { @Documented @ConditionalOnClass(RefreshScope.class) @ConditionalOnBean(RefreshAutoConfiguration.class) + @ConditionalOnProperty(value = "eureka.client.refresh.enable", havingValue = "true", matchIfMissing = true) @interface ConditionalOnRefreshScope { } @@ -390,6 +391,11 @@ public class EurekaClientAutoConfiguration { } + @ConditionalOnProperty(value = "eureka.client.refresh.enable", havingValue = "false") + static class OnPropertyDisabled { + + } + } @Configuration diff --git a/spring-cloud-netflix-eureka-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-netflix-eureka-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json index aea1bb649..2d964f336 100644 --- a/spring-cloud-netflix-eureka-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-netflix-eureka-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -6,6 +6,12 @@ "description": "Enables the Eureka health check handler.", "type": "java.lang.Boolean" }, + { + "defaultValue": true, + "name": "eureka.client.refresh.enable", + "description": "Determines whether the EurekaClient instance can be refreshed or not(If disabled none of the Eureka client properties will be refreshable).", + "type": "java.lang.Boolean" + }, { "defaultValue": true, "name": "ribbon.eureka.enabled", @@ -13,4 +19,4 @@ "type": "java.lang.Boolean" } ] -} \ No newline at end of file +} diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/ConditionalOnRefreshScopeTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/ConditionalOnRefreshScopeTests.java index ec0ff8024..cdacd32f4 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/ConditionalOnRefreshScopeTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/ConditionalOnRefreshScopeTests.java @@ -21,6 +21,7 @@ import org.junit.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; +import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration.ConditionalOnMissingRefreshScope; import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration.ConditionalOnRefreshScope; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -44,11 +45,31 @@ public class ConditionalOnRefreshScopeTests { }); } + @Test + public void refreshScopeIncludedAndPropertyDisabled() { + new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class)) + .withPropertyValues("eureka.client.refresh.enable=false") + .withUserConfiguration(Beans.class).run(c -> { + assertThat(c).hasSingleBean( + org.springframework.cloud.context.scope.refresh.RefreshScope.class); + assertThat(c).doesNotHaveBean("foo"); + assertThat(c.getBean("bar")).isEqualTo("bar"); + }); + } + @Test public void refreshScopeNotIncluded() { new ApplicationContextRunner().withUserConfiguration(Beans.class).run(c -> { assertThat(c).doesNotHaveBean("foo"); + assertThat(c.getBean("bar")).isEqualTo("bar"); }); + + new ApplicationContextRunner().withUserConfiguration(Beans.class) + .withPropertyValues("eureka.client.refresh.enable=false").run(c -> { + assertThat(c).doesNotHaveBean("foo"); + assertThat(c.getBean("bar")).isEqualTo("bar"); + }); } @Configuration @@ -60,6 +81,12 @@ public class ConditionalOnRefreshScopeTests { return "foo"; } + @Bean + @ConditionalOnMissingRefreshScope + public String bar() { + return "bar"; + } + } } diff --git a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilter.java b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilter.java index 6f250986f..3a69d25ca 100644 --- a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilter.java +++ b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilter.java @@ -184,8 +184,8 @@ public class SendResponseFilter extends ZuulFilter { } } - //cleanup ThreadLocal when we are all done - if(buffers != null) { + // cleanup ThreadLocal when we are all done + if (buffers != null) { buffers.remove(); }