diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonClientConfiguration.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonClientConfiguration.java index a96d39b7..512d3b19 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonClientConfiguration.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonClientConfiguration.java @@ -26,6 +26,8 @@ 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.ribbon.PropertiesFactory; +import org.springframework.cloud.netflix.ribbon.RibbonClientName; +import org.springframework.cloud.netflix.ribbon.RibbonUtils; import org.springframework.cloud.netflix.ribbon.ServerIntrospector; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -41,10 +43,6 @@ import com.netflix.loadbalancer.ServerList; import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList; import com.netflix.niws.loadbalancer.NIWSDiscoveryPing; -import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses; -import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity; -import static org.springframework.cloud.netflix.ribbon.RibbonUtils.setRibbonProperty; - /** * Preprocessor that configures defaults for eureka-discovered ribbon clients. Such as: * @zone, NIWSServerListClassName, DeploymentContextBasedVipAddresses, @@ -62,7 +60,7 @@ public class EurekaRibbonClientConfiguration { @Value("${ribbon.eureka.approximateZoneFromHostname:false}") private boolean approximateZoneFromHostname = false; - @Value("${ribbon.client.name}") + @RibbonClientName private String serviceId = "client"; @Autowired(required = false) @@ -145,9 +143,7 @@ public class EurekaRibbonClientConfiguration { } } } - setRibbonProperty(this.serviceId, DeploymentContextBasedVipAddresses.key(), - this.serviceId); - setRibbonProperty(this.serviceId, EnableZoneAffinity.key(), "true"); + RibbonUtils.initializeRibbonDefaults(serviceId); } } diff --git a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RestClientRibbonConfiguration.java b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RestClientRibbonConfiguration.java index 10a598e5..a4827be5 100644 --- a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RestClientRibbonConfiguration.java +++ b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RestClientRibbonConfiguration.java @@ -17,11 +17,11 @@ package org.springframework.cloud.netflix.ribbon; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; + import com.netflix.client.AbstractLoadBalancerAwareClient; import com.netflix.client.RetryHandler; import com.netflix.client.config.IClientConfig; @@ -36,7 +36,7 @@ import com.netflix.servo.monitor.Monitors; @Configuration @RibbonAutoConfiguration.ConditionalOnRibbonRestClient class RestClientRibbonConfiguration { - @Value("${ribbon.client.name}") + @RibbonClientName private String name = "client"; /** diff --git a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientConfiguration.java b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientConfiguration.java index 0724db36..dc2ff6bd 100644 --- a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientConfiguration.java +++ b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientConfiguration.java @@ -21,7 +21,6 @@ import javax.annotation.PostConstruct; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.CookiePolicy; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.commons.httpclient.HttpClientConfiguration; @@ -70,7 +69,7 @@ public class RibbonClientConfiguration { public static final int DEFAULT_CONNECT_TIMEOUT = 1000; public static final int DEFAULT_READ_TIMEOUT = 1000; - @Value("${ribbon.client.name}") + @RibbonClientName private String name = "client"; // TODO: maybe re-instate autowired load balancers: identified by name they could be diff --git a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientName.java b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientName.java new file mode 100644 index 00000000..122edb62 --- /dev/null +++ b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonClientName.java @@ -0,0 +1,26 @@ +package org.springframework.cloud.netflix.ribbon; + +import org.springframework.beans.factory.annotation.Value; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation at the field or method/constructor parameter level that injects the + * Ribbon Client Name that got allocated at runtime. Provides a convenient + * alternative for @Value("${ribbon.client.name}"). + * + * @author Spencer Gibb + * @since 2.0.0 + */ +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, + ElementType.ANNOTATION_TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Value("${ribbon.client.name}") +public @interface RibbonClientName { + +} diff --git a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonUtils.java b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonUtils.java index d316f30a..63a2645b 100644 --- a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonUtils.java +++ b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonUtils.java @@ -2,6 +2,7 @@ package org.springframework.cloud.netflix.ribbon; import java.net.URI; +import com.netflix.client.config.IClientConfigKey; import org.springframework.util.StringUtils; import org.springframework.web.util.UriComponentsBuilder; import com.netflix.client.config.CommonClientConfigKey; @@ -14,6 +15,17 @@ import com.netflix.loadbalancer.Server; import java.util.HashMap; import java.util.Map; +import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses; +import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity; +import static com.netflix.client.config.CommonClientConfigKey.Port; +import static com.netflix.client.config.CommonClientConfigKey.SecurePort; +import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_CONNECT_TIMEOUT; +import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_FOLLOW_REDIRECTS; +import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_MAX_TOTAL_CONNECTIONS; +import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_OK_TO_RETRY_ON_ALL_OPERATIONS; +import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_PORT; +import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_READ_TIMEOUT; + /** * @author Spencer Gibb * @author Jacques-Etienne Beaudet @@ -22,7 +34,6 @@ import java.util.Map; public class RibbonUtils { public static final String VALUE_NOT_SET = "__not__set__"; - public static final String DEFAULT_NAMESPACE = "ribbon"; private static final Map unsecureSchemeMapping; @@ -33,6 +44,100 @@ public class RibbonUtils { unsecureSchemeMapping.put("ws", "wss"); } + public static void initializeRibbonDefaults(String serviceId) { + setRibbonProperty(serviceId, DeploymentContextBasedVipAddresses.key(), + serviceId); + setRibbonProperty(serviceId, EnableZoneAffinity.key(), "true"); + } + + public static RibbonProperties from(IClientConfig config) { + return new RibbonProperties(config); + } + + //TODO: add more commonly used properties + //TODO: refactor s-c-netflix to use this class where possible + public static class RibbonProperties { + private final IClientConfig config; + + RibbonProperties(IClientConfig config) { + this.config = config; + } + + public Integer getPort() { + return get(Port); + } + + public int port() { + return get(Port, DEFAULT_PORT); + } + + public Integer getSecurePort() { + return this.config.get(SecurePort); + } + + public Boolean getSecure() { + return get(CommonClientConfigKey.IsSecure); + } + + public boolean isSecure() { + return get(CommonClientConfigKey.IsSecure, false); + } + + public Integer getReadTimeout() { + return get(CommonClientConfigKey.ReadTimeout); + } + + public int readTimeout() { + return get(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT); + } + + public Integer getConnectTimeout() { + return get(CommonClientConfigKey.ConnectTimeout); + } + + public int connectTimeout() { + return get(CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT); + } + + public Boolean getOkToRetryOnAllOperations() { + return get(CommonClientConfigKey.OkToRetryOnAllOperations); + } + + public boolean isOkToRetryOnAllOperations() { + return get(CommonClientConfigKey.OkToRetryOnAllOperations, + DEFAULT_OK_TO_RETRY_ON_ALL_OPERATIONS); + } + + public Boolean getFollowRedirects() { + return get(CommonClientConfigKey.FollowRedirects); + } + + public boolean isFollowRedirects() { + return get(CommonClientConfigKey.FollowRedirects, + DEFAULT_FOLLOW_REDIRECTS); + } + + public Integer getMaxTotalConnections() { + return get(CommonClientConfigKey.MaxTotalConnections); + } + + public int maxTotalConnections() { + return get(CommonClientConfigKey.MaxTotalConnections, DEFAULT_MAX_TOTAL_CONNECTIONS); + } + + public boolean has(IClientConfigKey key) { + return this.config.containsProperty(key); + } + + public T get(IClientConfigKey key) { + return this.config.get(key); + } + + public T get(IClientConfigKey key, T defaultValue) { + return this.config.get(key, defaultValue); + } + } + public static void setRibbonProperty(String serviceId, String suffix, String value) { // how to set the namespace properly? String key = getRibbonKey(serviceId, suffix); diff --git a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/apache/HttpClientRibbonConfiguration.java b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/apache/HttpClientRibbonConfiguration.java index ef11920f..25c4dfbd 100644 --- a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/apache/HttpClientRibbonConfiguration.java +++ b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/apache/HttpClientRibbonConfiguration.java @@ -20,13 +20,14 @@ package org.springframework.cloud.netflix.ribbon.apache; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; + import javax.annotation.PreDestroy; + import org.apache.http.client.config.RequestConfig; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.impl.client.CloseableHttpClient; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; @@ -35,9 +36,11 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancedBackOffPolicyFa import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory; import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory; import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory; +import org.springframework.cloud.netflix.ribbon.RibbonClientName; +import org.springframework.cloud.netflix.ribbon.ServerIntrospector; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.cloud.netflix.ribbon.ServerIntrospector; + import com.netflix.client.AbstractLoadBalancerAwareClient; import com.netflix.client.RetryHandler; import com.netflix.client.config.CommonClientConfigKey; @@ -53,7 +56,7 @@ import com.netflix.servo.monitor.Monitors; @ConditionalOnClass(name = "org.apache.http.client.HttpClient") @ConditionalOnProperty(name = "ribbon.httpclient.enabled", matchIfMissing = true) public class HttpClientRibbonConfiguration { - @Value("${ribbon.client.name}") + @RibbonClientName private String name = "client"; @Configuration diff --git a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpRibbonConfiguration.java b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpRibbonConfiguration.java index 5bb8f696..3418d691 100644 --- a/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpRibbonConfiguration.java +++ b/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpRibbonConfiguration.java @@ -17,12 +17,10 @@ package org.springframework.cloud.netflix.ribbon.okhttp; -import okhttp3.ConnectionPool; -import okhttp3.OkHttpClient; - import java.util.concurrent.TimeUnit; + import javax.annotation.PreDestroy; -import org.springframework.beans.factory.annotation.Value; + import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; @@ -31,9 +29,11 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancedBackOffPolicyFa import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory; import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory; import org.springframework.cloud.commons.httpclient.OkHttpClientFactory; +import org.springframework.cloud.netflix.ribbon.RibbonClientName; import org.springframework.cloud.netflix.ribbon.ServerIntrospector; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; + import com.netflix.client.AbstractLoadBalancerAwareClient; import com.netflix.client.RetryHandler; import com.netflix.client.config.CommonClientConfigKey; @@ -42,6 +42,9 @@ import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.servo.monitor.Monitors; +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; + /** * @author Spencer Gibb */ @@ -49,7 +52,7 @@ import com.netflix.servo.monitor.Monitors; @ConditionalOnProperty("ribbon.okhttp.enabled") @ConditionalOnClass(name = "okhttp3.OkHttpClient") public class OkHttpRibbonConfiguration { - @Value("${ribbon.client.name}") + @RibbonClientName private String name = "client"; @Configuration