Commit 6654d320 by Spencer Gibb

create SpringClientFactory for ribbon to not fail on client creation if…

create SpringClientFactory for ribbon to not fail on client creation if LoadBalancer is already created. SpringClientFactory is not a static factory, but an instance factory. Remove unused hystrix configuration classes.
parent f934b88a
...@@ -27,7 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean ...@@ -27,7 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.EurekaDiscoverClient; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.servo.ServoMetricReader; import org.springframework.cloud.netflix.servo.ServoMetricReader;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.context.SmartLifecycle; import org.springframework.context.SmartLifecycle;
...@@ -140,7 +140,12 @@ public class EurekaClientConfiguration implements SmartLifecycle, Ordered { ...@@ -140,7 +140,12 @@ public class EurekaClientConfiguration implements SmartLifecycle, Ordered {
@Bean @Bean
public DiscoveryClient discoveryClient() { public DiscoveryClient discoveryClient() {
return new EurekaDiscoverClient(); return new EurekaDiscoveryClient();
}
@Bean
public SpringClientFactory springClientFactory() {
return new SpringClientFactory();
} }
@Bean @Bean
......
package org.springframework.cloud.netflix; package org.springframework.cloud.netflix.eureka;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
...@@ -8,7 +8,7 @@ import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; ...@@ -8,7 +8,7 @@ import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
public class EurekaDiscoverClient implements DiscoveryClient { public class EurekaDiscoveryClient implements DiscoveryClient {
@Autowired @Autowired
private EurekaInstanceConfigBean config; private EurekaInstanceConfigBean config;
......
...@@ -15,9 +15,7 @@ ...@@ -15,9 +15,7 @@
*/ */
package org.springframework.cloud.netflix.hystrix; package org.springframework.cloud.netflix.hystrix;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import java.lang.annotation.*; import java.lang.annotation.*;
...@@ -27,34 +25,6 @@ import java.lang.annotation.*; ...@@ -27,34 +25,6 @@ import java.lang.annotation.*;
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
@Import(HystrixConfigurationSelector.class) @Import(HystrixConfiguration.class)
public @interface EnableHystrix { public @interface EnableHystrix {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
* opposed to standard Java interface-based proxies ({@code false}). The default is
* {@code false}. <strong>Applicable only if {@link #mode()} is set to
* {@link org.springframework.context.annotation.AdviceMode#PROXY}</strong>.
* <p>Note that setting this attribute to {@code true} will affect <em>all</em>
* Spring-managed beans requiring proxying, not just those marked with
* {@code @Transactional}. For example, other beans marked with Spring's
* {@code @Async} annotation will be upgraded to subclass proxying at the same
* time. This approach has no negative impact in practice unless one is explicitly
* expecting one type of proxy vs another, e.g. in tests.
*/
boolean proxyTargetClass() default false;
/**
* Indicate how transactional advice should be applied. The default is
* {@link org.springframework.context.annotation.AdviceMode#PROXY}.
* @see org.springframework.context.annotation.AdviceMode
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* Indicate the ordering of the execution of the transaction advisor
* when multiple advices are applied at a specific joinpoint.
* The default is {@link org.springframework.core.Ordered#LOWEST_PRECEDENCE}.
*/
int order() default Ordered.LOWEST_PRECEDENCE;
} }
\ No newline at end of file
...@@ -29,6 +29,7 @@ import org.springframework.beans.factory.DisposableBean; ...@@ -29,6 +29,7 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.GaugeService; import org.springframework.boot.actuate.metrics.GaugeService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.SmartLifecycle; import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -65,7 +66,7 @@ public class HystrixConfiguration implements ImportAware { ...@@ -65,7 +66,7 @@ public class HystrixConfiguration implements ImportAware {
} }
@Bean @Bean
// TODO: add enable/disable @ConditionalOnExpression("${hystrix.stream.endpoint.enabled:true}")
// TODO: make it @ConditionalOnWebApp (need a nested class) // TODO: make it @ConditionalOnWebApp (need a nested class)
public HystrixStreamEndpoint hystrixStreamEndpoint() { public HystrixStreamEndpoint hystrixStreamEndpoint() {
return new HystrixStreamEndpoint(); return new HystrixStreamEndpoint();
...@@ -81,20 +82,6 @@ public class HystrixConfiguration implements ImportAware { ...@@ -81,20 +82,6 @@ public class HystrixConfiguration implements ImportAware {
+ importMetadata.getClassName()); + importMetadata.getClassName());
} }
@Autowired(required = false)
void setConfigurers(Collection<HystrixConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException(
"Only one HystrixConfigurer may exist");
}
// TODO: create CircuitBreakerConfigurer API
// CircuitBreakerConfigurer configurer = configurers.iterator().next();
// this.txManager = configurer.annotationDrivenTransactionManager();
}
@Configuration @Configuration
@ConditionalOnClass(GaugeService.class) @ConditionalOnClass(GaugeService.class)
protected static class HystrixMetricsPollerConfiguration implements SmartLifecycle { protected static class HystrixMetricsPollerConfiguration implements SmartLifecycle {
......
/*
* Copyright 2013-2014 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.hystrix;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.AdviceModeImportSelector;
import org.springframework.context.annotation.AutoProxyRegistrar;
/**
* @author Spencer Gibb
*/
public class HystrixConfigurationSelector extends AdviceModeImportSelector<EnableHystrix> {
/**
* The name of the AspectJ transaction management @{@code Configuration} class.
*/
private static final String TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration";
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[]{AutoProxyRegistrar.class.getName(), HystrixConfiguration.class.getName()};
case ASPECTJ:
return new String[]{TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
}
/*
* Copyright 2013-2014 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.hystrix;
/**
* @author Spencer Gibb
*/
public interface HystrixConfigurer {
}
...@@ -8,7 +8,6 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -8,7 +8,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import com.netflix.client.ClientFactory;
import com.netflix.loadbalancer.BaseLoadBalancer; import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
...@@ -22,6 +21,9 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { ...@@ -22,6 +21,9 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient {
@Autowired @Autowired
private ServerListInitializer serverListInitializer; private ServerListInitializer serverListInitializer;
@Autowired
private SpringClientFactory clientFactory;
private Map<String, ILoadBalancer> balancers = new HashMap<String, ILoadBalancer>(); private Map<String, ILoadBalancer> balancers = new HashMap<String, ILoadBalancer>();
public RibbonLoadBalancerClient(List<BaseLoadBalancer> balancers) { public RibbonLoadBalancerClient(List<BaseLoadBalancer> balancers) {
...@@ -35,7 +37,7 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { ...@@ -35,7 +37,7 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient {
serverListInitializer.initialize(serviceId); serverListInitializer.initialize(serviceId);
ILoadBalancer loadBalancer = this.balancers.get(serviceId); ILoadBalancer loadBalancer = this.balancers.get(serviceId);
if (loadBalancer == null) { if (loadBalancer == null) {
loadBalancer = ClientFactory.getNamedLoadBalancer(serviceId); loadBalancer = clientFactory.getNamedLoadBalancer(serviceId);
} }
Server server = loadBalancer.chooseServer("default"); Server server = loadBalancer.chooseServer("default");
if (server == null) { if (server == null) {
......
...@@ -6,9 +6,9 @@ import static com.netflix.client.config.CommonClientConfigKey.NFLoadBalancerRule ...@@ -6,9 +6,9 @@ import static com.netflix.client.config.CommonClientConfigKey.NFLoadBalancerRule
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListClassName; import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListClassName;
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListFilterClassName; import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListFilterClassName;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.ribbon.ServerListInitializer; import org.springframework.cloud.netflix.ribbon.ServerListInitializer;
import com.netflix.client.ClientFactory;
import com.netflix.config.ConfigurationManager; import com.netflix.config.ConfigurationManager;
import com.netflix.config.DeploymentContext.ContextKey; import com.netflix.config.DeploymentContext.ContextKey;
import com.netflix.discovery.EurekaClientConfig; import com.netflix.discovery.EurekaClientConfig;
...@@ -28,17 +28,19 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList; ...@@ -28,17 +28,19 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
*/ */
public class EurekaRibbonInitializer implements ServerListInitializer { public class EurekaRibbonInitializer implements ServerListInitializer {
private EurekaClientConfig client; private EurekaClientConfig clientConfig;
private SpringClientFactory clientFactory;
public EurekaRibbonInitializer(EurekaClientConfig client) { public EurekaRibbonInitializer(EurekaClientConfig clientConfig, SpringClientFactory clientFactory) {
this.client = client; this.clientConfig = clientConfig;
} this.clientFactory = clientFactory;
}
@Override @Override
public void initialize(String serviceId) { public void initialize(String serviceId) {
if (client != null if (clientConfig != null
&& ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone) == null) { && ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone) == null) {
String[] zones = client.getAvailabilityZones(client.getRegion()); String[] zones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
String zone = zones != null && zones.length > 0 ? zones[0] : null; String zone = zones != null && zones.length > 0 ? zones[0] : null;
if (zone != null) { if (zone != null) {
// You can set this with archaius.deployment.* (maybe requires // You can set this with archaius.deployment.* (maybe requires
...@@ -58,7 +60,7 @@ public class EurekaRibbonInitializer implements ServerListInitializer { ...@@ -58,7 +60,7 @@ public class EurekaRibbonInitializer implements ServerListInitializer {
setProp(serviceId, NIWSServerListFilterClassName.key(), setProp(serviceId, NIWSServerListFilterClassName.key(),
ZonePreferenceServerListFilter.class.getName()); ZonePreferenceServerListFilter.class.getName());
setProp(serviceId, EnableZoneAffinity.key(), "true"); setProp(serviceId, EnableZoneAffinity.key(), "true");
ILoadBalancer loadBalancer = ClientFactory.getNamedLoadBalancer(serviceId); ILoadBalancer loadBalancer = clientFactory.getNamedLoadBalancer(serviceId);
wrapServerList(loadBalancer); wrapServerList(loadBalancer);
} }
...@@ -71,6 +73,7 @@ public class EurekaRibbonInitializer implements ServerListInitializer { ...@@ -71,6 +73,7 @@ public class EurekaRibbonInitializer implements ServerListInitializer {
// This is optional: you can use the native Eureka AWS features as long as // This is optional: you can use the native Eureka AWS features as long as
// the server zone is populated. TODO: find a way to back off if AWS // the server zone is populated. TODO: find a way to back off if AWS
// metadata *is* available. // metadata *is* available.
// @see com.netflix.appinfo.AmazonInfo.Builder
dynamic.setServerListImpl(new DomainExtractingServerList(list)); dynamic.setServerListImpl(new DomainExtractingServerList(list));
} }
} }
......
...@@ -20,6 +20,7 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; ...@@ -20,6 +20,7 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.ServerListInitializer; import org.springframework.cloud.netflix.ribbon.ServerListInitializer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -40,10 +41,10 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList; ...@@ -40,10 +41,10 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
public class RibbonEurekaAutoConfiguration { public class RibbonEurekaAutoConfiguration {
@Autowired(required=false) @Autowired(required=false)
private EurekaClientConfig client; private EurekaClientConfig clientConfig;
@Bean @Bean
public ServerListInitializer serverListInitializer() { public ServerListInitializer serverListInitializer(SpringClientFactory clientFactory) {
return new EurekaRibbonInitializer(client); return new EurekaRibbonInitializer(clientConfig, clientFactory);
} }
} }
...@@ -16,13 +16,13 @@ import org.apache.commons.io.IOUtils; ...@@ -16,13 +16,13 @@ import org.apache.commons.io.IOUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.ribbon.ServerListInitializer; import org.springframework.cloud.netflix.ribbon.ServerListInitializer;
import org.springframework.cloud.netflix.zuul.RibbonCommand; import org.springframework.cloud.netflix.zuul.RibbonCommand;
import org.springframework.cloud.netflix.zuul.SpringFilter; import org.springframework.cloud.netflix.zuul.SpringFilter;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import com.netflix.client.ClientException; import com.netflix.client.ClientException;
import com.netflix.client.ClientFactory;
import com.netflix.client.http.HttpRequest.Verb; import com.netflix.client.http.HttpRequest.Verb;
import com.netflix.client.http.HttpResponse; import com.netflix.client.http.HttpResponse;
import com.netflix.hystrix.exception.HystrixRuntimeException; import com.netflix.hystrix.exception.HystrixRuntimeException;
...@@ -71,10 +71,9 @@ public class RibbonRoutingFilter extends SpringFilter { ...@@ -71,10 +71,9 @@ public class RibbonRoutingFilter extends SpringFilter {
String serviceId = (String) context.get("serviceId"); String serviceId = (String) context.get("serviceId");
//TODO: should this be an interface or just config?
getBean(ServerListInitializer.class).initialize(serviceId); getBean(ServerListInitializer.class).initialize(serviceId);
RestClient restClient = (RestClient) ClientFactory.getNamedClient(serviceId); RestClient restClient = getBean(SpringClientFactory.class).namedClient(serviceId, RestClient.class);
String uri = request.getRequestURI(); String uri = request.getRequestURI();
if (context.get("requestURI") != null) { if (context.get("requestURI") != null) {
......
...@@ -21,9 +21,9 @@ import static org.junit.Assert.assertTrue; ...@@ -21,9 +21,9 @@ import static org.junit.Assert.assertTrue;
import org.junit.After; import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean; import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
import com.netflix.client.ClientFactory;
import com.netflix.config.ConfigurationManager; import com.netflix.config.ConfigurationManager;
import com.netflix.config.DeploymentContext.ContextKey; import com.netflix.config.DeploymentContext.ContextKey;
import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.ILoadBalancer;
...@@ -45,10 +45,11 @@ public class EurekaRibbonInitializerTests { ...@@ -45,10 +45,11 @@ public class EurekaRibbonInitializerTests {
public void basicConfigurationCreatedForLoadBalancer() { public void basicConfigurationCreatedForLoadBalancer() {
EurekaClientConfigBean client = new EurekaClientConfigBean(); EurekaClientConfigBean client = new EurekaClientConfigBean();
client.getAvailabilityZones().put(client.getRegion(), "foo"); client.getAvailabilityZones().put(client.getRegion(), "foo");
EurekaRibbonInitializer initializer = new EurekaRibbonInitializer( SpringClientFactory clientFactory = new SpringClientFactory();
client); EurekaRibbonInitializer initializer = new EurekaRibbonInitializer(
client, clientFactory);
initializer.initialize("service"); initializer.initialize("service");
ILoadBalancer balancer = ClientFactory.getNamedLoadBalancer("service"); ILoadBalancer balancer = clientFactory.getNamedLoadBalancer("service");
assertNotNull(balancer); assertNotNull(balancer);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> aware = (ZoneAwareLoadBalancer<Server>) balancer; ZoneAwareLoadBalancer<Server> aware = (ZoneAwareLoadBalancer<Server>) balancer;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment