Commit 3ed982d2 by Spencer Gibb

Introduce Ribbon ServerIntrospector.

Allows ribbon load balancer implementations to answer questions like isSecure(Server).
parent a38ba340
/*
* Copyright 2013-2015 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 com.netflix.loadbalancer.Server;
/**
* @author Spencer Gibb
*/
public class DefaultServerIntrospector implements ServerIntrospector {
@Override
public boolean isSecure(Server server) {
// Can we do better?
return (""+server.getPort()).endsWith("443");
}
}
......@@ -26,10 +26,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.ClassUtils;
import org.springframework.web.util.UriComponentsBuilder;
import com.netflix.appinfo.InstanceInfo.PortType;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ConfigurationBasedServerList;
......@@ -44,7 +42,6 @@ import com.netflix.loadbalancer.ServerListFilter;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import com.netflix.niws.client.http.RestClient;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import com.netflix.servo.monitor.Monitors;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.client.apache4.ApacheHttpClient4;
......@@ -95,9 +92,9 @@ public class RibbonClientConfiguration {
}
/**
* Create a Netflix {@link RestClient} integrated with Ribbon if none already exists in the
* application context. It is not required for Ribbon to work properly and is therefore
* created lazily if ever another component requires it.
* Create a Netflix {@link RestClient} integrated with Ribbon if none already exists
* in the application context. It is not required for Ribbon to work properly and is
* therefore created lazily if ever another component requires it.
*
* @param config the configuration to use by the underlying Ribbon instance
* @param loadBalancer the load balancer to use by the underlying Ribbon instance
......@@ -106,8 +103,9 @@ public class RibbonClientConfiguration {
@Bean
@Lazy
@ConditionalOnMissingBean
public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer) {
RestClient client = new OverrideRestClient(config);
public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer,
ServerIntrospector serverIntrospector) {
RestClient client = new OverrideRestClient(config, serverIntrospector);
client.setLoadBalancer(loadBalancer);
Monitors.registerObject("Client_" + this.name, client);
return client;
......@@ -140,34 +138,33 @@ public class RibbonClientConfiguration {
return new RibbonLoadBalancerContext(loadBalancer, config);
}
@Bean
@ConditionalOnMissingBean
public ServerIntrospector serverIntrospector() {
return new DefaultServerIntrospector();
}
static class OverrideRestClient extends RestClient {
protected OverrideRestClient(IClientConfig ncc) {
private ServerIntrospector serverIntrospector;
protected OverrideRestClient(IClientConfig ncc,
ServerIntrospector serverIntrospector) {
super();
this.serverIntrospector = serverIntrospector;
initWithNiwsConfig(ncc);
}
@Override
public URI reconstructURIWithServer(Server server, URI original) {
String scheme = original.getScheme();
if (!"https".equals(scheme) && isSecure(server)) {
original = UriComponentsBuilder.fromUri(original).scheme("https").build().toUri();
if (!"https".equals(scheme) && serverIntrospector.isSecure(server)) {
original = UriComponentsBuilder.fromUri(original).scheme("https").build()
.toUri();
}
return super.reconstructURIWithServer(server, original);
}
private boolean isSecure(Server server) {
if (ClassUtils.isPresent("com.netflix.niws.loadbalancer.DiscoveryEnabledServer",
null)) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer enabled = (DiscoveryEnabledServer) server;
return enabled.getInstanceInfo().isPortEnabled(PortType.SECURE);
}
}
// Can we do better?
return (""+server.getPort()).endsWith("443");
}
@Override
protected Client apacheHttpClientSpecificInitialization() {
ApacheHttpClient4 apache = (ApacheHttpClient4) super
......
/*
* Copyright 2013-2015 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 com.netflix.loadbalancer.Server;
/**
* @author Spencer Gibb
*/
public interface ServerIntrospector {
boolean isSecure(Server server);
}
......@@ -177,7 +177,7 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
return result;
}
private <C> C getInstance(String name, Class<C> type) {
public <C> C getInstance(String name, Class<C> type) {
AnnotationConfigApplicationContext context = getContext(name);
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type).length > 0) {
return context.getBean(type);
......
......@@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
......@@ -101,6 +102,11 @@ public class EurekaRibbonClientConfiguration {
return serverList;
}
@Bean
public ServerIntrospector serverIntrospector() {
return new EurekaServerIntrospector();
}
@PostConstruct
public void preprocess() {
String zone = ConfigurationManager.getDeploymentContext().getValue(
......
/*
* Copyright 2013-2015 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.eureka;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.loadbalancer.Server;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
/**
* @author Spencer Gibb
*/
public class EurekaServerIntrospector extends DefaultServerIntrospector {
@Override
public boolean isSecure(Server server) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer enabled = (DiscoveryEnabledServer) server;
return enabled.getInstanceInfo().isPortEnabled(InstanceInfo.PortType.SECURE);
}
return super.isSecure(server);
}
}
......@@ -47,7 +47,7 @@ public class RibbonClientConfigurationTests {
static class TestRestClient extends RibbonClientConfiguration.OverrideRestClient {
private TestRestClient(IClientConfig ncc) {
super(ncc);
super(ncc, new DefaultServerIntrospector());
}
@Override
......
......@@ -25,6 +25,7 @@ import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.ribbon.eureka.EurekaRibbonClientPreprocessorIntegrationTests.TestConfiguration;
import org.springframework.context.annotation.Configuration;
......@@ -63,6 +64,11 @@ public class EurekaRibbonClientPreprocessorIntegrationTests {
NIWSDiscoveryPing.class.cast(getLoadBalancer().getPing());
}
@Test
public void serverIntrospectorDefaultsToEureka() throws Exception {
EurekaServerIntrospector.class.cast(this.factory.getInstance("foo", ServerIntrospector.class));
}
@SuppressWarnings("unchecked")
private ZoneAwareLoadBalancer<Server> getLoadBalancer() {
return (ZoneAwareLoadBalancer<Server>) this.factory
......
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