Merge pull request #1749 from bijukunjummen/GH-1334
GH-1334: Support for eagerly initializing zuul Ribbon contexts
This commit is contained in:
@@ -864,6 +864,21 @@ public class MyClass {
|
||||
}
|
||||
----
|
||||
|
||||
[[ribbon-child-context-eager-load]]
|
||||
=== Caching of Ribbon Configuration
|
||||
|
||||
Each Ribbon named client has a corresponding child Application Context that Spring Cloud maintains, this application context is lazily loaded up on the first request to the named client.
|
||||
This lazy loading behavior can be changed to instead eagerly load up these child Application contexts at startup by specifying the names of the Ribbon clients.
|
||||
|
||||
.application.yml
|
||||
----
|
||||
ribbon:
|
||||
eager-load:
|
||||
enabled: true
|
||||
clients: client1, client2, client3
|
||||
----
|
||||
|
||||
|
||||
[[spring-cloud-feign]]
|
||||
== Declarative REST Client: Feign
|
||||
|
||||
@@ -2041,6 +2056,18 @@ public class AddResponseHeaderFilter extends ZuulFilter {
|
||||
|
||||
If an exception is thrown during any portion of the Zuul filter lifecycle, the error filters are executed. The `SendErrorFilter` is only run if `RequestContext.getThrowable()` is not `null`. It then sets specific `javax.servlet.error.*` attributes in the request and forwards the request to the Spring Boot error page.
|
||||
|
||||
==== Zuul Eager Application Context Loading
|
||||
|
||||
Zuul internally uses Ribbon for calling the remote url's and Ribbon clients are by default lazily loaded up by Spring Cloud on first call.
|
||||
This behavior can be changed for Zuul using the following configuration and will result in the child Ribbon related Application contexts being eagerly loaded up at application startup time.
|
||||
|
||||
.application.yml
|
||||
----
|
||||
zuul:
|
||||
ribbon:
|
||||
eager-load:
|
||||
enabled: true
|
||||
----
|
||||
|
||||
== Polyglot support with Sidecar
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.ribbon;
|
||||
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Responsible for eagerly creating the child application context holding the Ribbon
|
||||
* related configuration
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
public class RibbonApplicationContextInitializer
|
||||
implements ApplicationListener<ApplicationReadyEvent> {
|
||||
|
||||
private final SpringClientFactory springClientFactory;
|
||||
|
||||
//List of Ribbon client names
|
||||
private final List<String> clientNames;
|
||||
|
||||
public RibbonApplicationContextInitializer(SpringClientFactory springClientFactory,
|
||||
List<String> clientNames) {
|
||||
this.springClientFactory = springClientFactory;
|
||||
this.clientNames = clientNames;
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
if (clientNames != null) {
|
||||
for (String clientName : clientNames) {
|
||||
this.springClientFactory.getContext(clientName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
initialize();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.actuator.HasFeatures;
|
||||
import org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory;
|
||||
@@ -53,16 +54,21 @@ import com.netflix.ribbon.Ribbon;
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ IClient.class, RestTemplate.class, AsyncRestTemplate.class, Ribbon.class})
|
||||
@RibbonClients
|
||||
@AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
|
||||
@AutoConfigureBefore({LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class})
|
||||
@EnableConfigurationProperties(RibbonEagerLoadProperties.class)
|
||||
public class RibbonAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<RibbonClientSpecification> configurations = new ArrayList<>();
|
||||
|
||||
@Autowired
|
||||
private RibbonEagerLoadProperties ribbonEagerLoadProperties;
|
||||
|
||||
@Bean
|
||||
public HasFeatures ribbonFeature() {
|
||||
@@ -99,6 +105,13 @@ public class RibbonAutoConfiguration {
|
||||
public PropertiesFactory propertiesFactory() {
|
||||
return new PropertiesFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "ribbon.eager-load.enabled", matchIfMissing = false)
|
||||
public RibbonApplicationContextInitializer ribbonApplicationContextInitializer() {
|
||||
return new RibbonApplicationContextInitializer(springClientFactory(),
|
||||
ribbonEagerLoadProperties.getClients());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(HttpRequest.class)
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.ribbon;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* Configuration Properties to indicate which Ribbon configurations
|
||||
* should be eagerly loaded up
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "ribbon.eager-load")
|
||||
public class RibbonEagerLoadProperties {
|
||||
private boolean enabled = false;
|
||||
private List<String> clients;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public List<String> getClients() {
|
||||
return clients;
|
||||
}
|
||||
|
||||
public void setClients(List<String> clients) {
|
||||
this.clients = clients;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -115,5 +115,10 @@ public class SpringClientFactory extends NamedContextFactory<RibbonClientSpecifi
|
||||
return instantiateWithConfig(getContext(name), type, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AnnotationConfigApplicationContext getContext(String name) {
|
||||
return super.getContext(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import java.util.Map;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.web.ErrorController;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
|
||||
@@ -31,6 +32,7 @@ import org.springframework.cloud.client.actuator.HasFeatures;
|
||||
import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
|
||||
import org.springframework.cloud.client.discovery.event.HeartbeatMonitor;
|
||||
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.cloud.netflix.zuul.filters.CompositeRouteLocator;
|
||||
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
|
||||
import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
|
||||
@@ -58,6 +60,7 @@ import com.netflix.zuul.http.ZuulServlet;
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({ ZuulProperties.class })
|
||||
@@ -161,6 +164,14 @@ public class ZuulConfiguration {
|
||||
return new SendForwardFilter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "zuul.ribbon.eager-load.enabled", matchIfMissing = false)
|
||||
public ZuulRouteApplicationContextInitializer zuulRoutesApplicationContextInitiazer(
|
||||
SpringClientFactory springClientFactory) {
|
||||
return new ZuulRouteApplicationContextInitializer(springClientFactory,
|
||||
zuulProperties);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class ZuulFilterConfiguration {
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.zuul;
|
||||
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonApplicationContextInitializer;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Responsible for taking in the list of registered serviceid's (Ribbon client names)
|
||||
* and creating the Spring {@link org.springframework.context.ApplicationContext} on
|
||||
* start-up
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
|
||||
public class ZuulRouteApplicationContextInitializer extends
|
||||
RibbonApplicationContextInitializer {
|
||||
public ZuulRouteApplicationContextInitializer(SpringClientFactory springClientFactory,
|
||||
ZuulProperties zuulProperties) {
|
||||
super(springClientFactory, getServiceIdsFromZuulProps(zuulProperties));
|
||||
}
|
||||
|
||||
private static List<String> getServiceIdsFromZuulProps(ZuulProperties zuulProperties) {
|
||||
Map<String, ZuulProperties.ZuulRoute> zuulRoutes = zuulProperties.getRoutes();
|
||||
Collection<ZuulProperties.ZuulRoute> registeredRoutes = zuulRoutes.values();
|
||||
List<String> serviceIds = new ArrayList<>();
|
||||
if (registeredRoutes != null) {
|
||||
for (ZuulProperties.ZuulRoute route: registeredRoutes) {
|
||||
String serviceId = route.getServiceId();
|
||||
if (serviceId != null) {
|
||||
serviceIds.add(serviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return serviceIds;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.ribbon;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {RibbonAutoConfiguration.class,
|
||||
ArchaiusAutoConfiguration.class, RibbonApplicationContextInitializerTests.RibbonInitializerConfig.class})
|
||||
@DirtiesContext
|
||||
public class RibbonApplicationContextInitializerTests {
|
||||
|
||||
@Autowired
|
||||
private SpringClientFactory springClientFactory;
|
||||
|
||||
@Test
|
||||
public void testContextShouldInitalizeChildContexts() {
|
||||
|
||||
// Context should have been initialized and an instance of Foo created
|
||||
assertThat(Foo.getInstanceCount()).isEqualTo(1);
|
||||
ApplicationContext ctx = springClientFactory.getContext("testspec");
|
||||
|
||||
assertThat(Foo.getInstanceCount()).isEqualTo(1);
|
||||
Foo foo = ctx.getBean("foo", Foo.class);
|
||||
assertThat(foo).isNotNull();
|
||||
}
|
||||
|
||||
static class FooConfig {
|
||||
|
||||
@Bean
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@RibbonClient(name="testspec", configuration = FooConfig.class)
|
||||
static class RibbonInitializerConfig {
|
||||
|
||||
@Bean
|
||||
public RibbonApplicationContextInitializer ribbonApplicationContextInitializer(
|
||||
SpringClientFactory springClientFactory) {
|
||||
return new RibbonApplicationContextInitializer(springClientFactory,
|
||||
Arrays.asList("testspec"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger();
|
||||
|
||||
public Foo() {
|
||||
INSTANCE_COUNT.incrementAndGet();
|
||||
}
|
||||
|
||||
public static int getInstanceCount() {
|
||||
return INSTANCE_COUNT.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.ribbon;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(properties = {
|
||||
"ribbon.eager-load.enabled=true",
|
||||
"ribbon.eager-load.clients=testspec1,testspec2"
|
||||
})
|
||||
@DirtiesContext
|
||||
public class RibbonClientsEagerInitializationTest {
|
||||
|
||||
@Test
|
||||
public void contextsShouldBeInitialized() {
|
||||
assertThat(Foo1.getInstanceCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
static class FooConfig {
|
||||
@Bean
|
||||
public Foo1 foo() {
|
||||
return new Foo1();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RibbonClients(
|
||||
value = {
|
||||
@RibbonClient(name="testspec1", configuration = FooConfig.class),
|
||||
@RibbonClient(name="testspec2", configuration = FooConfig.class),
|
||||
@RibbonClient(name="testspec3", configuration = FooConfig.class),
|
||||
})
|
||||
static class RibbonConfig {
|
||||
}
|
||||
|
||||
static class Foo1 {
|
||||
private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger();
|
||||
|
||||
public Foo1() {
|
||||
INSTANCE_COUNT.incrementAndGet();
|
||||
}
|
||||
|
||||
public static int getInstanceCount() {
|
||||
return INSTANCE_COUNT.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.cloud.netflix.zuul.filters.route;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClient;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClients;
|
||||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(value = { "zuul.routes.myroute.service-id=eager",
|
||||
"zuul.ribbon.eager-load.enabled=true" })
|
||||
@DirtiesContext
|
||||
public class EagerLoadOfZuulConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void testEagerLoading() {
|
||||
// Child context FooConfig should have been eagerly instantiated..
|
||||
assertThat(Foo.getInstanceCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
@EnableZuulProxy
|
||||
@RibbonClients(@RibbonClient(name = "eager", configuration = FooConfig.class))
|
||||
static class TestConfig {
|
||||
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger();
|
||||
|
||||
public Foo() {
|
||||
INSTANCE_COUNT.incrementAndGet();
|
||||
}
|
||||
|
||||
public static int getInstanceCount() {
|
||||
return INSTANCE_COUNT.get();
|
||||
}
|
||||
}
|
||||
|
||||
static class FooConfig {
|
||||
|
||||
@Bean
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.cloud.netflix.zuul.filters.route;
|
||||
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import com.netflix.loadbalancer.ServerList;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClient;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClients;
|
||||
import org.springframework.cloud.netflix.ribbon.StaticServerList;
|
||||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, value = {
|
||||
"zuul.routes.myroute.service-id=eager", "zuul.routes.myroute.path=/eager/**" })
|
||||
@DirtiesContext
|
||||
public class LazyLoadOfZuulConfigurationTests {
|
||||
|
||||
@Value("${local.server.port}")
|
||||
protected int port;
|
||||
|
||||
@Test
|
||||
public void testEagerLoading() {
|
||||
// Child context FooConfig should be lazily created..
|
||||
assertThat(Foo.getInstanceCount()).isEqualTo(0);
|
||||
|
||||
String uri = String.format("http://localhost:%d/eager/sample", this.port);
|
||||
|
||||
ResponseEntity<String> result = new TestRestTemplate().getForEntity(uri,
|
||||
String.class);
|
||||
|
||||
// the instance should be available now..
|
||||
assertThat(Foo.getInstanceCount()).isEqualTo(1);
|
||||
|
||||
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(result.getBody()).isEqualTo("sample");
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
@EnableZuulProxy
|
||||
@RibbonClients(@RibbonClient(name = "eager", configuration = FooConfig.class))
|
||||
static class TestConfig {
|
||||
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger();
|
||||
|
||||
public Foo() {
|
||||
INSTANCE_COUNT.incrementAndGet();
|
||||
}
|
||||
|
||||
public static int getInstanceCount() {
|
||||
return INSTANCE_COUNT.get();
|
||||
}
|
||||
}
|
||||
|
||||
static class FooConfig {
|
||||
|
||||
@Bean
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private int port;
|
||||
|
||||
@Bean
|
||||
public ServerList<Server> ribbonServerList() {
|
||||
return new StaticServerList<>(new Server("localhost", this.port));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@RestController
|
||||
static class SampleWebConfig {
|
||||
|
||||
@RequestMapping("/sample")
|
||||
public String sampleEndpoint() {
|
||||
return "sample";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user