From 59c0010be31b6bbad20b67e2da35894899e9b170 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Sat, 22 Feb 2020 14:40:17 +0100 Subject: [PATCH] Switch from Ribbon to SC LoadBalancer (#240) * WIP * Remove repeated dependency. * Gitignore fix. * Implement Spring Cloud LoadBalancer-based DependencyFeignClientAutoConfiguration and DependencyLoadBalancerAutoConfiguration. * Fix dependency-based configurations. Add ZookeeperServiceInstanceListSupplier. Add LoadBalancerZookeeperAutoConfiguration. * Adjust tests to changes in code. * Adjust tests to changes in code. Add missing license Strings. Refactor. * Add BlockingDependencyLoadBalancerConfiguration. Remove condition from ZookeeperDependenciesAutoConfiguration. * Switch EmptyResponse to chooseDefault(). Fix DependencyRestTemplateAutoConfiguration. Change return type for BlockingDependencyLoadBalancerConfiguration. * Fix zookeeper-specific BlockingLoadBalancerClient implementation. * Remove zookeeper-specific LoadBalancerClient and ReactorExchangeFilterFunction implementations following a team discussion. Remove Ribbon-specific entries from docs. Add javadocs. Co-authored-by: Marcin Grzejszczak --- README.adoc | 16 +-- docs/src/main/asciidoc/README.adoc | 11 +- docs/src/main/asciidoc/_configprops.adoc | 3 +- docs/src/main/asciidoc/intro.adoc | 5 +- docs/src/main/asciidoc/sagan-index.adoc | 4 +- .../main/asciidoc/spring-cloud-zookeeper.adoc | 83 +++++------ pom.xml | 2 +- spring-cloud-zookeeper-config/pom.xml | 4 + ...perPropertySourceLocatorFailFastTests.java | 58 ++++---- spring-cloud-zookeeper-core/pom.xml | 14 ++ spring-cloud-zookeeper-discovery/pom.xml | 15 +- ...onalOnLoadBalancerForZookeeperEnabled.java | 36 +++++ ...oadBalancerZookeeperAutoConfiguration.java | 44 ++++++ .../ZookeeperLoadBalancerConfiguration.java | 63 ++++++++ .../ZookeeperServiceInstanceListSupplier.java | 88 ++++++++++++ .../DependenciesBasedLoadBalancer.java | 111 -------------- ...ependencyFeignClientAutoConfiguration.java | 131 +++++++++-------- ...pendencyRestTemplateAutoConfiguration.java | 5 + .../dependency/LoadBalancerType.java | 31 ---- .../discovery/dependency/StickyRule.java | 81 ----------- .../dependency/ZookeeperDependencies.java | 22 +-- ...ookeeperDependenciesAutoConfiguration.java | 2 +- .../dependency/ZookeeperDependency.java | 19 +-- .../main/resources/META-INF/spring.factories | 3 +- ...erDiscoveryAutoRegistrationFalseTests.java | 15 +- ...althIndicatorWithNestedStructureTests.java | 2 +- .../ZookeeperDiscoverySecurePortTests.java | 4 +- .../discovery/ZookeeperDiscoveryTests.java | 17 ++- .../ZookeeprDiscoveryNonWebAppTests.java | 3 +- .../dependency/DependencyConfig.java | 2 +- .../discovery/dependency/StickyRuleTests.java | 135 ------------------ .../ZookeeperDependenciesTests.java | 4 +- ...overyWithDependenciesIntegrationTests.java | 63 +++----- ...erDiscoveryWithDyingDependenciesTests.java | 2 +- .../discovery/test/CommonTestConfig.java | 3 +- ...ibbon.yml => application-loadbalancer.yml} | 4 +- .../src/test/resources/application.yml | 2 +- 37 files changed, 468 insertions(+), 639 deletions(-) create mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ConditionalOnLoadBalancerForZookeeperEnabled.java create mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/LoadBalancerZookeeperAutoConfiguration.java create mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperLoadBalancerConfiguration.java create mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceInstanceListSupplier.java delete mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesBasedLoadBalancer.java delete mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/LoadBalancerType.java delete mode 100644 spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/StickyRule.java delete mode 100644 spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/StickyRuleTests.java rename spring-cloud-zookeeper-discovery/src/test/resources/{application-ribbon.yml => application-loadbalancer.yml} (79%) diff --git a/README.adoc b/README.adoc index 26dda61a..fd774920 100644 --- a/README.adoc +++ b/README.adoc @@ -28,9 +28,8 @@ This project provides Zookeeper integrations for Spring Boot applications throug autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. With a few annotations, you can quickly enable and configure the common patterns inside your application and build large distributed systems with Zookeeper based -components. The provided patterns include Service Discovery and Configuration. Integration -with Spring Cloud Netflix provides Intelligent Routing (Zuul), Client Side Load Balancing -(Ribbon), and Circuit Breaker (Hystrix). +components. The provided patterns include Service Discovery and Configuration. The project +also provides client-side load-balancing via integration with Spring Cloud LoadBalancer. :doctype: book @@ -51,17 +50,16 @@ with Spring Cloud Netflix provides Intelligent Routing (Zuul), Client Side Load == Zookeeper overview -ZooKeeper is a centralized service for maintaining configuration information, naming, -providing distributed synchronization, and providing group services. See the -https://zookeeper.apache.org[Zookeeper site] for more information. Spring Cloud Zookeeper -also builds on the https://curator.apache.org[Apache Curator] project, which started life -at Netflix. +ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. +See the +https://zookeeper.apache.org[Zookeeper site] for more information. +Spring Cloud Zookeeper also builds on the https://curator.apache.org[Apache Curator] project, which started life at Netflix. == Spring Cloud Zookeeper Features Spring Cloud Zookeeper includes the following features: -* Spring Cloud `DiscoveryClient` implementation (supports Ribbon and Zuul) +* Spring Cloud `DiscoveryClient` implementation (supports Spring Cloud LoadBalancer) * Zookeeper-based `PropertySource` loaded during the 'bootstrap' phase == Running the Sample diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc index 5af314a6..dad6f4fe 100644 --- a/docs/src/main/asciidoc/README.adoc +++ b/docs/src/main/asciidoc/README.adoc @@ -6,17 +6,16 @@ include::_attributes.adoc[] == Zookeeper overview -ZooKeeper is a centralized service for maintaining configuration information, naming, -providing distributed synchronization, and providing group services. See the -https://zookeeper.apache.org[Zookeeper site] for more information. Spring Cloud Zookeeper -also builds on the https://curator.apache.org[Apache Curator] project, which started life -at Netflix. +ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. +See the +https://zookeeper.apache.org[Zookeeper site] for more information. +Spring Cloud Zookeeper also builds on the https://curator.apache.org[Apache Curator] project, which started life at Netflix. == Spring Cloud Zookeeper Features Spring Cloud Zookeeper includes the following features: -* Spring Cloud `DiscoveryClient` implementation (supports Ribbon and Zuul) +* Spring Cloud `DiscoveryClient` implementation (supports Spring Cloud LoadBalancer) * Zookeeper-based `PropertySource` loaded during the 'bootstrap' phase == Running the Sample diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index 5496309e..0fb80778 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -5,8 +5,7 @@ |spring.cloud.zookeeper.block-until-connected-unit | | The unit of time related to blocking on connection to Zookeeper. |spring.cloud.zookeeper.block-until-connected-wait | 10 | Wait time to block on connection to Zookeeper. |spring.cloud.zookeeper.connect-string | localhost:2181 | Connection string to the Zookeeper cluster. -|spring.cloud.zookeeper.default-health-endpoint | | Default health endpoint that will be checked to verify that a dependency is alive. -|spring.cloud.zookeeper.dependencies | | Mapping of alias to ZookeeperDependency. From Ribbon perspective the alias is actually serviceID since Ribbon can't accept nested structures in serviceID. +|spring.cloud.zookeeper.dependencies | | Mapping of alias to ZookeeperDependency. From LoadBalancer perspective the alias is actually serviceID since SC LoadBalancer can't accept nested structures in serviceID. |spring.cloud.zookeeper.dependency-configurations | | |spring.cloud.zookeeper.dependency-names | | |spring.cloud.zookeeper.discovery.enabled | true | diff --git a/docs/src/main/asciidoc/intro.adoc b/docs/src/main/asciidoc/intro.adoc index 8cd2451e..5930b967 100644 --- a/docs/src/main/asciidoc/intro.adoc +++ b/docs/src/main/asciidoc/intro.adoc @@ -5,6 +5,5 @@ This project provides Zookeeper integrations for Spring Boot applications throug autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. With a few annotations, you can quickly enable and configure the common patterns inside your application and build large distributed systems with Zookeeper based -components. The provided patterns include Service Discovery and Configuration. Integration -with Spring Cloud Netflix provides Intelligent Routing (Zuul), Client Side Load Balancing -(Ribbon), and Circuit Breaker (Hystrix). +components. The provided patterns include Service Discovery and Configuration. The project +also provides client-side load-balancing via integration with Spring Cloud LoadBalancer. diff --git a/docs/src/main/asciidoc/sagan-index.adoc b/docs/src/main/asciidoc/sagan-index.adoc index 72d3e264..8c230337 100644 --- a/docs/src/main/asciidoc/sagan-index.adoc +++ b/docs/src/main/asciidoc/sagan-index.adoc @@ -6,8 +6,8 @@ Spring Cloud Zookeeper provides http://zookeeper.apache.org/[Apache Zookeeper] i ## Features * Service Discovery: instances can be registered with Zookeeper and clients can discover the instances using Spring-managed beans - * Supports Ribbon, the client side load-balancer via Spring Cloud Netflix - * Supports Zuul, a dynamic router and filter via Spring Cloud Netflix + * Supports Spring Cloud LoadBalancer - client-side load-balancing solution + * Supports Spring Cloud OpenFeign * Distributed Configuration: using Zookeeper as a data store ## Quick Start diff --git a/docs/src/main/asciidoc/spring-cloud-zookeeper.adoc b/docs/src/main/asciidoc/spring-cloud-zookeeper.adoc index 82defdd3..ef330e78 100644 --- a/docs/src/main/asciidoc/spring-cloud-zookeeper.adoc +++ b/docs/src/main/asciidoc/spring-cloud-zookeeper.adoc @@ -164,14 +164,14 @@ public String serviceUrl() { == Using Spring Cloud Zookeeper with Spring Cloud Netflix Components Spring Cloud Netflix supplies useful tools that work regardless of which `DiscoveryClient` -implementation you use. Feign, Turbine, Ribbon, and Zuul all work with Spring Cloud -Zookeeper. +implementation you use. +Feign and Spring Cloud LoadBalancer also work with Spring Cloud Zookeeper. -=== Ribbon with Zookeeper +=== Spring Cloud LoadBalancer with Zookeeper -Spring Cloud Zookeeper provides an implementation of Ribbon's `ServerList`. When you use -the `spring-cloud-starter-zookeeper-discovery`, Ribbon is autoconfigured to use the -`ZookeeperServerList` by default. +Spring Cloud Zookeeper provides an implementation of Spring Cloud LoadBalancer `ServiceInstanceListSupplier`. +When you use the `spring-cloud-starter-zookeeper-discovery`, Spring Cloud LoadBalancer is autoconfigured to use the +`ZookeeperServiceInstanceListSupplier` by default. [[spring-cloud-zookeeper-service-registry]] == Spring Cloud Zookeeper and Service Registry @@ -201,15 +201,13 @@ public void registerThings() { === Instance Status -Netflix Eureka supports having instances that are `OUT_OF_SERVICE` registered with the -server. These instances are not returned as active service instances. This is useful for -behaviors such as blue/green deployments. (Note that the Curator Service Discovery recipe -does not support this behavior.) Taking advantage of the flexible payload has let Spring -Cloud Zookeeper implement `OUT_OF_SERVICE` by updating some specific metadata and then -filtering on that metadata in the Ribbon `ZookeeperServerList`. The `ZookeeperServerList` -filters out all non-null instance statuses that do not equal `UP`. If the instance status -field is empty, it is considered to be `UP` for backwards compatibility. To change the -status of an instance, make a `POST` with `OUT_OF_SERVICE` to the `ServiceRegistry` +Netflix Eureka supports having instances that are `OUT_OF_SERVICE` registered with the server. +These instances are not returned as active service instances. +This is useful for behaviors such as blue/green deployments. +(Note that the Curator Service Discovery recipe does not support this behavior.) Taking advantage of the flexible payload has let Spring Cloud Zookeeper implement `OUT_OF_SERVICE` by updating some specific metadata and then filtering on that metadata in the Spring Cloud LoadBalancer `ZookeeperServiceInstanceListSupplier`. +The `ZookeeperServiceInstanceListSupplier` filters out all non-null instance statuses that do not equal `UP`. +If the instance status field is empty, it is considered to be `UP` for backwards compatibility. +To change the status of an instance, make a `POST` with `OUT_OF_SERVICE` to the `ServiceRegistry` instance status actuator endpoint, as shown in the following example: [source,sh,indent=0] @@ -290,14 +288,14 @@ name is `spring.cloud.zookeeper.dependencies`. [[spring-cloud-zookeeper-dependencies-setting-up-aliases]] ==== Aliases -Below the root property you have to represent each dependency as an alias. This is due to -the constraints of Ribbon, which requires that the application ID be placed in the URL. -Consequently, you cannot pass any complex path, suchas `/myApp/myRoute/name`). The alias -is the name you use instead of the `serviceId` for `DiscoveryClient`, `Feign`, or +Below the root property you have to represent each dependency as an alias. +This is due to the constraints of Spring Cloud LoadBalancer, which requires that the application ID be placed in the URL. +Consequently, you cannot pass any complex path, suchas `/myApp/myRoute/name`). +The alias is the name you use instead of the `serviceId` for `DiscoveryClient`, `Feign`, or `RestTemplate`. -In the previous examples, the aliases are `newsletter` and `mailing`. The following -example shows Feign usage with a `newsletter` alias: +In the previous examples, the aliases are `newsletter` and `mailing`. +The following example shows Feign usage with a `newsletter` alias: [source,java,indent=0] ---- @@ -310,19 +308,18 @@ public interface NewsletterService { ==== Path -The path is represented by the `path` YAML property and is the path under which the -dependency is registered under Zookeeper. As described in the -<>, Ribbon -operates on URLs. As a result, this path is not compliant with its requirement. +The path is represented by the `path` YAML property and is the path under which the dependency is registered under Zookeeper. +As described in the +<>, Spring Cloud LoadBalancer operates on URLs. +As a result, this path is not compliant with its requirement. That is why Spring Cloud Zookeeper maps the alias to the proper path. ==== Load Balancer Type The load balancer type is represented by `loadBalancerType` YAML property. -If you know what kind of load-balancing strategy has to be applied when calling this -particular dependency, you can provide it in the YAML file, and it is automatically -applied. You can choose one of the following load balancing strategies: +If you know what kind of load-balancing strategy has to be applied when calling this particular dependency, you can provide it in the YAML file, and it is automatically applied. +You can choose one of the following load balancing strategies: * STICKY: Once chosen, the instance is always called. * RANDOM: Picks an instance randomly. @@ -412,29 +409,15 @@ example: [[spring-cloud-zookeeper-dependencies-configuring]] === Configuring Spring Cloud Zookeeper Dependencies -You can set the following properties to enable or disable parts of Zookeeper Dependencies -functionalities: +You can set the following properties to enable or disable parts of Zookeeper Dependencies functionalities: -* `spring.cloud.zookeeper.dependencies`: If you do not set this property, you cannot use -Zookeeper Dependencies. -* `spring.cloud.zookeeper.dependency.ribbon.enabled` (enabled by default): Ribbon requires -either explicit global configuration or a particular one for a dependency. By turning on -this property, runtime load balancing strategy resolution is possible, and you can use the -`loadBalancerType` section of the Zookeeper Dependencies. The configuration that needs -this property has an implementation of `LoadBalancerClient` that delegates to the -`ILoadBalancer` presented in the next bullet. -* `spring.cloud.zookeeper.dependency.ribbon.loadbalancer` (enabled by default): Thanks to -this property, the custom `ILoadBalancer` knows that the part of the URI passed to Ribbon -might actually be the alias that has to be resolved to a proper path in Zookeeper. Without -this property, you cannot register applications under nested paths. -* `spring.cloud.zookeeper.dependency.headers.enabled` (enabled by default): This property -registers a `RibbonClient` that automatically appends appropriate headers and content -types with their versions, as presented in the Dependency configuration. Without this -setting, those two parameters do not work. -* `spring.cloud.zookeeper.dependency.resttemplate.enabled` (enabled by default): When -enabled, this property modifies the request headers of a `@LoadBalanced`-annotated -`RestTemplate` such that it passes headers and content type with the version set in -dependency configuration. Without this setting, those two parameters do not work. +* `spring.cloud.zookeeper.dependencies`: If you do not set this property, you cannot use Zookeeper Dependencies. +* `spring.cloud.zookeeper.dependency.loadbalancer.enabled` (enabled by default): Turns on Zookeeper-specific custom load-balancing strategies, including `ZookeeperServiceInstanceListSupplier` and dependency-based load-balanced `RestTemplate` setup. +* `spring.cloud.zookeeper.dependency.headers.enabled` (enabled by default): This property registers a `FeignBlockingLoadBalancerClient` that automatically appends appropriate headers and content types with their versions, as presented in the Dependency configuration. +Without this setting, those two parameters do not work. +* `spring.cloud.zookeeper.dependency.resttemplate.enabled` (enabled by default): When enabled, this property modifies the request headers of a `@LoadBalanced`-annotated +`RestTemplate` such that it passes headers and content type with the version set in dependency configuration. +Without this setting, those two parameters do not work. [[spring-cloud-zookeeper-dependency-watcher]] == Spring Cloud Zookeeper Dependency Watcher diff --git a/pom.xml b/pom.xml index 456aa5fb..d6ecee63 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.springframework.cloud spring-cloud-zookeeper 3.0.0.BUILD-SNAPSHOT pom @@ -169,6 +168,7 @@ 3.0.0.BUILD-SNAPSHOT 3.0.0.BUILD-SNAPSHOT 3.0.0.BUILD-SNAPSHOT + 6.1.1.Final diff --git a/spring-cloud-zookeeper-config/pom.xml b/spring-cloud-zookeeper-config/pom.xml index f4c665fc..d4aa18c4 100644 --- a/spring-cloud-zookeeper-config/pom.xml +++ b/spring-cloud-zookeeper-config/pom.xml @@ -30,6 +30,10 @@ org.springframework.cloud spring-cloud-zookeeper-core + + org.apache.curator + curator-x-discovery + org.springframework.cloud spring-cloud-context diff --git a/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocatorFailFastTests.java b/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocatorFailFastTests.java index aa2cf76f..c2d03154 100644 --- a/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocatorFailFastTests.java +++ b/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocatorFailFastTests.java @@ -18,58 +18,62 @@ package org.springframework.cloud.zookeeper.config; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + /** * @author Enrique Recarte Llorens + * @author Olga Maciaszek-Sharma */ public class ZookeeperPropertySourceLocatorFailFastTests { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Before - public void setUp() throws Exception { + public void setUp() { // This system property makes Curator fail faster, otherwise it takes 15 seconds // to trigger a retry System.setProperty("curator-default-connection-timeout", "0"); } @After - public void tearDown() throws Exception { + public void tearDown() { System.clearProperty("curator-default-connection-timeout"); } @Test - public void testFailFastFalseLoadsTheApplicationContext() throws Exception { - new SpringApplicationBuilder().sources(Config.class).web(WebApplicationType.NONE) - .run("--spring.application.name=testZookeeperPropertySourceLocatorFailFast", - "--spring.cloud.zookeeper.config.connectString=localhost:2188", - "--spring.cloud.zookeeper.baseSleepTimeMs=0", - "--spring.cloud.zookeeper.maxRetries=0", - "--spring.cloud.zookeeper.maxSleepMs=0", - "--spring.cloud.zookeeper.blockUntilConnectedWait=0", - "--spring.cloud.zookeeper.config.failFast=false"); + public void testFailFastFalseLoadsTheApplicationContext() { + assertThatCode(() -> { + new SpringApplicationBuilder().sources(Config.class) + .web(WebApplicationType.NONE) + .run("--spring.application.name=testZookeeperPropertySourceLocatorFailFast", + "--spring.cloud.zookeeper.config.connectString=localhost:2188", + "--spring.cloud.zookeeper.baseSleepTimeMs=0", + "--spring.cloud.zookeeper.maxRetries=0", + "--spring.cloud.zookeeper.maxSleepMs=0", + "--spring.cloud.zookeeper.blockUntilConnectedWait=0", + "--spring.cloud.zookeeper.config.failFast=false"); + }).doesNotThrowAnyException(); } @Test - public void testFailFastTrueDoesNotLoadTheApplicationContext() throws Exception { - expectedException.expect(Exception.class); - - new SpringApplicationBuilder().sources(Config.class).web(WebApplicationType.NONE) - .run("--spring.application.name=testZookeeperPropertySourceLocatorFailFast", - "--spring.cloud.zookeeper.config.connectString=localhost:2188", - "--spring.cloud.zookeeper.baseSleepTimeMs=0", - "--spring.cloud.zookeeper.maxRetries=0", - "--spring.cloud.zookeeper.maxSleepMs=0", - "--spring.cloud.zookeeper.blockUntilConnectedWait=0", - "--spring.cloud.zookeeper.config.failFast=true"); + public void testFailFastTrueDoesNotLoadTheApplicationContext() { + assertThatThrownBy(() -> { + new SpringApplicationBuilder().sources(Config.class) + .web(WebApplicationType.NONE) + .run("--spring.application.name=testZookeeperPropertySourceLocatorFailFast", + "--spring.cloud.zookeeper.config.connectString=localhost:2188", + "--spring.cloud.zookeeper.baseSleepTimeMs=0", + "--spring.cloud.zookeeper.maxRetries=0", + "--spring.cloud.zookeeper.maxSleepMs=0", + "--spring.cloud.zookeeper.blockUntilConnectedWait=0", + "--spring.cloud.zookeeper.config.failFast=true"); + }) + .isNotNull(); } @SpringBootApplication diff --git a/spring-cloud-zookeeper-core/pom.xml b/spring-cloud-zookeeper-core/pom.xml index bc9897f5..ad30ea43 100644 --- a/spring-cloud-zookeeper-core/pom.xml +++ b/spring-cloud-zookeeper-core/pom.xml @@ -26,6 +26,15 @@ + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + org.springframework.boot spring-boot-configuration-processor @@ -50,6 +59,11 @@ spring-cloud-commons true + + org.apache.curator + curator-x-discovery + true + org.apache.curator curator-framework diff --git a/spring-cloud-zookeeper-discovery/pom.xml b/spring-cloud-zookeeper-discovery/pom.xml index 70b7e09c..3b8de605 100644 --- a/spring-cloud-zookeeper-discovery/pom.xml +++ b/spring-cloud-zookeeper-discovery/pom.xml @@ -38,6 +38,11 @@ spring-cloud-commons true + + org.springframework.cloud + spring-cloud-starter-loadbalancer + true + org.springframework.boot spring-boot-starter @@ -73,6 +78,11 @@ spring-cloud-starter-openfeign true + + io.github.openfeign + feign-core + true + org.springframework.boot spring-boot-autoconfigure-processor @@ -88,11 +98,6 @@ spring-cloud-config-server true - - org.springframework.cloud - spring-cloud-starter-loadbalancer - true - org.springframework.boot spring-boot-starter-web diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ConditionalOnLoadBalancerForZookeeperEnabled.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ConditionalOnLoadBalancerForZookeeperEnabled.java new file mode 100644 index 00000000..c9a65ad7 --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ConditionalOnLoadBalancerForZookeeperEnabled.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015-2019 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 + * + * https://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.zookeeper.discovery; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +/** + * Wrapper annotation to enable Spring Cloud LoadBalancer for Zookeeper. + * + * @author Olga Maciaszek-Sharma + * @since 3.0.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +@ConditionalOnProperty(value = "spring.cloud.zookeeper.loadbalancer.enabled", matchIfMissing = true) +public @interface ConditionalOnLoadBalancerForZookeeperEnabled { +} diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/LoadBalancerZookeeperAutoConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/LoadBalancerZookeeperAutoConfiguration.java new file mode 100644 index 00000000..db066349 --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/LoadBalancerZookeeperAutoConfiguration.java @@ -0,0 +1,44 @@ +/* + * Copyright 2015-2019 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 + * + * https://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.zookeeper.discovery; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer; +import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients; +import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration; +import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled; +import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependenciesAutoConfiguration; +import org.springframework.context.annotation.Configuration; + +/** + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} that sets up Spring Cloud LoadBalancer for Zookeeper. + * + * @author Olga Maciaszek-Sharma + * @since 3.0.0 + */ +@Configuration(proxyBeanMethods = false) +@EnableConfigurationProperties +@ConditionalOnZookeeperEnabled +@ConditionalOnBean(ReactiveLoadBalancer.Factory.class) +@ConditionalOnLoadBalancerForZookeeperEnabled +@AutoConfigureAfter({LoadBalancerAutoConfiguration.class, ZookeeperDependenciesAutoConfiguration.class}) +@LoadBalancerClients(defaultConfiguration = ZookeeperLoadBalancerConfiguration.class) +public class LoadBalancerZookeeperAutoConfiguration { +} diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperLoadBalancerConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperLoadBalancerConfiguration.java new file mode 100644 index 00000000..51b0404d --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperLoadBalancerConfiguration.java @@ -0,0 +1,63 @@ +/* + * Copyright 2015-2019 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 + * + * https://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.zookeeper.discovery; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager; +import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier; +import org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier; +import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; +import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +/** + * Zookeeper-specific {@link ServiceInstanceListSupplier} that provides a delegate that + * filters available instances based on status retrieved from Zookeeper. + * + * @author Olga Maciaszek-Sharma + * @since 3.0.0 + */ +@Configuration(proxyBeanMethods = false) +public class ZookeeperLoadBalancerConfiguration { + + @Bean + @ConditionalOnBean(DiscoveryClient.class) + @ConditionalOnMissingBean + public ServiceInstanceListSupplier zookeeperDiscoveryClientServiceInstanceListSupplier( + DiscoveryClient discoveryClient, Environment env, + ApplicationContext context, + ZookeeperDependencies zookeeperDependencies) { + DiscoveryClientServiceInstanceListSupplier firstDelegate = new DiscoveryClientServiceInstanceListSupplier( + discoveryClient, env); + ZookeeperServiceInstanceListSupplier secondDelegate = new ZookeeperServiceInstanceListSupplier(firstDelegate, + zookeeperDependencies); + ObjectProvider cacheManagerProvider = context + .getBeanProvider(LoadBalancerCacheManager.class); + if (cacheManagerProvider.getIfAvailable() != null) { + return new CachingServiceInstanceListSupplier(secondDelegate, + cacheManagerProvider.getIfAvailable()); + } + return secondDelegate; + } + +} diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceInstanceListSupplier.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceInstanceListSupplier.java new file mode 100644 index 00000000..42c830dc --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceInstanceListSupplier.java @@ -0,0 +1,88 @@ +/* + * Copyright 2015-2019 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 + * + * https://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.zookeeper.discovery; + +import java.util.ArrayList; +import java.util.List; + +import reactor.core.publisher.Flux; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; +import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies; +import org.springframework.util.StringUtils; + +import static org.springframework.cloud.zookeeper.support.StatusConstants.INSTANCE_STATUS_KEY; +import static org.springframework.cloud.zookeeper.support.StatusConstants.STATUS_UP; + +/** + * A {@link ServiceInstanceListSupplier} implementation that filters available instances based on status retrieved from Zookeeper. + * + * @author Olga Maciaszek-Sharma + * @since 3.0.0 + */ +public class ZookeeperServiceInstanceListSupplier implements ServiceInstanceListSupplier { + + private final ServiceInstanceListSupplier delegate; + private final String serviceId; + + public ZookeeperServiceInstanceListSupplier(ServiceInstanceListSupplier delegate, + ZookeeperDependencies zookeeperDependencies) { + this.delegate = delegate; + this.serviceId = getServiceIdFromDepsOrClientName(delegate + .getServiceId(), zookeeperDependencies); + } + + private String getServiceIdFromDepsOrClientName(String delegateServiceId, + ZookeeperDependencies zookeeperDependencies) { + String serviceIdFromDeps = zookeeperDependencies + .getPathForAlias(delegateServiceId); + return StringUtils.hasText(serviceIdFromDeps) ? serviceIdFromDeps + : delegateServiceId; + } + + @Override + public String getServiceId() { + return serviceId; + } + + @Override + public Flux> get() { + return delegate.get().map(this::filteredByZookeeperStatusUp); + } + + private List filteredByZookeeperStatusUp(List serviceInstances) { + ArrayList filteredInstances = new ArrayList<>(); + for (ServiceInstance serviceInstance : serviceInstances) { + if (serviceInstance instanceof ZookeeperServiceInstance) { + org.apache.curator.x.discovery.ServiceInstance zookeeperServiceInstance = ((ZookeeperServiceInstance) serviceInstance) + .getServiceInstance(); + String instanceStatus = null; + if (zookeeperServiceInstance.getPayload() != null + && zookeeperServiceInstance.getPayload().getMetadata() != null) { + instanceStatus = zookeeperServiceInstance.getPayload().getMetadata() + .get(INSTANCE_STATUS_KEY); + } + if (!StringUtils.hasText(instanceStatus) // backwards compatibility + || instanceStatus.equalsIgnoreCase(STATUS_UP)) { + filteredInstances.add(serviceInstance); + } + } + } + return filteredInstances; + } +} diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesBasedLoadBalancer.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesBasedLoadBalancer.java deleted file mode 100644 index ce77277f..00000000 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesBasedLoadBalancer.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2015-2019 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 - * - * https://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.zookeeper.discovery.dependency; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * LoadBalancer that delegates to other rules depending on the provided load balancing - * strategy in the {@link ZookeeperDependency#getLoadBalancerType()}. - * - * @author Marcin Grzejszczak - * @since 1.0.0 - */ -public class DependenciesBasedLoadBalancer /*extends DynamicServerListLoadBalancer*/ { - - private static final Log log = LogFactory.getLog(DependenciesBasedLoadBalancer.class); - - //private final Map ruleCache = new ConcurrentHashMap<>(); - - private final ZookeeperDependencies zookeeperDependencies; - - public DependenciesBasedLoadBalancer(ZookeeperDependencies zookeeperDependencies/*, - ServerList serverList, IClientConfig config, IPing iPing*/) { - //super(config); - this.zookeeperDependencies = zookeeperDependencies; - //setServersList(serverList.getInitialListOfServers()); - //setPing(iPing); - //setServerListImpl(serverList); - } - - // FIXME: 3.0.0 - //@Override - //public Server chooseServer(Object key) { - // String keyAsString; - // if ("default".equals(key)) { // this is the default hint, use name instead - // keyAsString = getName(); - // } - // else { - // keyAsString = (String) key; - // } - // ZookeeperDependency dependency = this.zookeeperDependencies - // .getDependencyForAlias(keyAsString); - // log.debug(String.format("Current dependencies are [%s]", - // this.zookeeperDependencies)); - // if (dependency == null) { - // log.debug(String.format( - // "No dependency found for alias [%s] - will use the default rule which is [%s]", - // keyAsString, this.rule)); - // return this.rule.choose(key); - // } - // cacheEntryIfMissing(keyAsString, dependency); - // log.debug(String.format( - // "Will try to retrieve dependency for key [%s]. Current cache contents [%s]", - // keyAsString, this.ruleCache)); - // updateListOfServers(); - // return this.ruleCache.get(keyAsString).choose(key); - //} - // - //private void cacheEntryIfMissing(String keyAsString, ZookeeperDependency dependency) { - // if (!this.ruleCache.containsKey(keyAsString)) { - // log.debug(String.format("Cache doesn't contain entry for [%s]", keyAsString)); - // this.ruleCache.put(keyAsString, - // chooseRuleForLoadBalancerType(dependency.getLoadBalancerType())); - // } - //} - // - //private IRule chooseRuleForLoadBalancerType(LoadBalancerType type) { - // switch (type) { - // case ROUND_ROBIN: - // return getRoundRobinRule(); - // case RANDOM: - // return getRandomRule(); - // case STICKY: - // return getStickyRule(); - // default: - // throw new IllegalArgumentException("Unknown load balancer type " + type); - // } - //} - // - //private RoundRobinRule getRoundRobinRule() { - // return new RoundRobinRule(this); - //} - // - //private IRule getRandomRule() { - // RandomRule randomRule = new RandomRule(); - // randomRule.setLoadBalancer(this); - // return randomRule; - //} - // - //private IRule getStickyRule() { - // StickyRule stickyRule = new StickyRule(getRoundRobinRule()); - // stickyRule.setLoadBalancer(this); - // return stickyRule; - //} - -} diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyFeignClientAutoConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyFeignClientAutoConfiguration.java index 22a4e51d..ab208bb2 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyFeignClientAutoConfiguration.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyFeignClientAutoConfiguration.java @@ -16,80 +16,99 @@ package org.springframework.cloud.zookeeper.discovery.dependency; -import feign.Client; +import java.io.IOException; +import java.net.URI; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import feign.Client; +import feign.Request; +import feign.Response; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; +import org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration; +import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient; +import org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration; import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; /** * Configuration for ensuring that headers are set for a given dependency when Feign is * used. * * @author Marcin Grzejszczak + * @author Olga Maciaszek-Sharma * @since 1.0.0 */ @Configuration(proxyBeanMethods = false) @ConditionalOnDependenciesPassed @ConditionalOnZookeeperEnabled @ConditionalOnProperty(value = "spring.cloud.zookeeper.dependency.headers.enabled", matchIfMissing = true) -@ConditionalOnClass({ Client.class/*, LoadBalancerFeignClient.class*/ }) -/*@AutoConfigureAfter({ RibbonAutoConfiguration.class, - FeignRibbonClientAutoConfiguration.class })*/ +@ConditionalOnClass({Client.class, FeignBlockingLoadBalancerClient.class}) +@ConditionalOnBean(BlockingLoadBalancerClient.class) +@AutoConfigureAfter({FeignLoadBalancerAutoConfiguration.class, BlockingLoadBalancerClientAutoConfiguration.class}) public class DependencyFeignClientAutoConfiguration { - // FIXME: 3.0.0 - //@Autowired(required = false) - //private LoadBalancerFeignClient ribbonClient; - // - //@Autowired - //private ZookeeperDependencies zookeeperDependencies; - // - //@Autowired - //private CachingSpringLoadBalancerFactory loadBalancerFactory; - // - //@Autowired - //private SpringClientFactory springClientFactory; - // - //@Bean - //@Primary - //Client dependencyBasedFeignClient() { - // return new LoadBalancerFeignClient(new Client.Default(null, null), - // this.loadBalancerFactory, this.springClientFactory) { - // - // @Override - // public Response execute(Request request, Request.Options options) - // throws IOException { - // URI asUri = URI.create(request.url()); - // String clientName = asUri.getHost(); - // ZookeeperDependency dependencyForAlias = DependencyFeignClientAutoConfiguration.this.zookeeperDependencies - // .getDependencyForAlias(clientName); - // Map> headers = getUpdatedHeadersIfPossible( - // request, dependencyForAlias); - // if (DependencyFeignClientAutoConfiguration.this.ribbonClient != null) { - // return DependencyFeignClientAutoConfiguration.this.ribbonClient - // .execute(request(request, headers), options); - // } - // return super.execute(request(request, headers), options); - // } - // - // private Request request(Request request, - // Map> headers) { - // return Request.create(request.method(), request.url(), headers, - // request.body(), request.charset()); - // } - // - // private Map> getUpdatedHeadersIfPossible( - // Request request, ZookeeperDependency dependencyForAlias) { - // if (dependencyForAlias != null) { - // return Collections.unmodifiableMap(new HashMap<>( - // dependencyForAlias.getUpdatedHeaders(request.headers()))); - // } - // return request.headers(); - // } - // - // }; - //} + private final FeignBlockingLoadBalancerClient feignLoadBalancerClient; + + private final ZookeeperDependencies zookeeperDependencies; + + private final BlockingLoadBalancerClient loadBalancerClient; + + public DependencyFeignClientAutoConfiguration(@Autowired(required = false) FeignBlockingLoadBalancerClient feignLoadBalancerClient, + ZookeeperDependencies zookeeperDependencies, BlockingLoadBalancerClient loadBalancerClient) { + this.feignLoadBalancerClient = feignLoadBalancerClient; + this.zookeeperDependencies = zookeeperDependencies; + this.loadBalancerClient = loadBalancerClient; + } + + @Bean + @Primary + Client dependencyBasedFeignClient() { + return new FeignBlockingLoadBalancerClient(new Client.Default(null, null), + loadBalancerClient) { + + @Override + public Response execute(Request request, Request.Options options) + throws IOException { + URI asUri = URI.create(request.url()); + String clientName = asUri.getHost(); + ZookeeperDependency dependencyForAlias = DependencyFeignClientAutoConfiguration.this.zookeeperDependencies + .getDependencyForAlias(clientName); + Map> headers = getUpdatedHeadersIfPossible( + request, dependencyForAlias); + if (DependencyFeignClientAutoConfiguration.this.feignLoadBalancerClient != null) { + return DependencyFeignClientAutoConfiguration.this.feignLoadBalancerClient + .execute(request(request, headers), options); + } + return super.execute(request(request, headers), options); + } + + private Request request(Request request, + Map> headers) { + return Request.create(request.httpMethod(), request.url(), headers, + request.body(), request.charset(), request.requestTemplate()); + } + + private Map> getUpdatedHeadersIfPossible( + Request request, ZookeeperDependency dependencyForAlias) { + if (dependencyForAlias != null) { + return Collections.unmodifiableMap(new HashMap<>( + dependencyForAlias.getUpdatedHeaders(request.headers()))); + } + return request.headers(); + } + + }; + } } diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyRestTemplateAutoConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyRestTemplateAutoConfiguration.java index bac58dec..794a111a 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyRestTemplateAutoConfiguration.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyRestTemplateAutoConfiguration.java @@ -26,9 +26,11 @@ import java.util.Map; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled; +import org.springframework.cloud.zookeeper.discovery.ConditionalOnLoadBalancerForZookeeperEnabled; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; @@ -41,12 +43,15 @@ import org.springframework.web.client.RestTemplate; * Customizes RestTemplate to support passing of params from dependency. * * @author Marcin Grzejszczak + * @author Olga Maciaszek-Sharma * @since 1.0.0 */ @Configuration(proxyBeanMethods = false) @ConditionalOnZookeeperEnabled +@ConditionalOnLoadBalancerForZookeeperEnabled @ConditionalOnDependenciesPassed @ConditionalOnProperty(value = "spring.cloud.zookeeper.dependency.resttemplate.enabled", matchIfMissing = true) +@ConditionalOnBean(RestTemplate.class) public class DependencyRestTemplateAutoConfiguration { @Autowired diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/LoadBalancerType.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/LoadBalancerType.java deleted file mode 100644 index 7e0c9043..00000000 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/LoadBalancerType.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2015-2019 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 - * - * https://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.zookeeper.discovery.dependency; - -/** - * @author Marcin Grzejszczak - * @author Spencer Gibb - * @since 1.0.0 - */ -public enum LoadBalancerType { - - /** - * Valid load balancer types. - */ - STICKY, RANDOM, ROUND_ROBIN - -} diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/StickyRule.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/StickyRule.java deleted file mode 100644 index 299dec19..00000000 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/StickyRule.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2015-2019 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 - * - * https://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.zookeeper.discovery.dependency; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Load balancing rule that returns always the same instance. - * - * Ported from {@code org.apache.curator.x.discovery.strategies.StickyStrategy} - * - * @author Marcin Grzejszczak - * @since 1.0.0 - */ -public class StickyRule /*extends AbstractLoadBalancerRule*/ { - - private static final Log log = LogFactory.getLog(StickyRule.class); - - //private final IRule masterStrategy; - - //private final AtomicReference ourInstance = new AtomicReference<>(null); - - private final AtomicInteger instanceNumber = new AtomicInteger(-1); - - // FIXME: 3.0.0 - //public StickyRule(IRule masterStrategy) { - // this.masterStrategy = masterStrategy; - //} - // - //@Override - //public void initWithNiwsConfig(IClientConfig iClientConfig) { - // - //} - // - //@Override - //public Server choose(Object key) { - // final List instances = getLoadBalancer().getServerList(true); - // log.debug(String.format("Instances taken from load balancer [%s]", instances)); - // Server localOurInstance = this.ourInstance.get(); - // log.debug(String.format("Current saved instance [%s]", localOurInstance)); - // if (!instances.contains(localOurInstance)) { - // this.ourInstance.compareAndSet(localOurInstance, null); - // } - // if (this.ourInstance.get() == null) { - // Server instance = this.masterStrategy.choose(key); - // if (this.ourInstance.compareAndSet(null, instance)) { - // this.instanceNumber.incrementAndGet(); - // } - // } - // return this.ourInstance.get(); - //} - - /** - * Each time a new instance is picked, an internal counter is incremented. This way - * you can track when/if the instance changes. The instance can change when the - * selected instance is not in the current list of instances returned by the instance - * provider - * @return instance number - */ - public int getInstanceNumber() { - return this.instanceNumber.get(); - } - -} diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependencies.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependencies.java index 635b14c4..9a49f89d 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependencies.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependencies.java @@ -24,7 +24,6 @@ import java.util.Map; import javax.annotation.PostConstruct; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.zookeeper.discovery.dependency.StubsConfiguration.DependencyPath; import org.springframework.util.StringUtils; @@ -35,6 +34,7 @@ import static org.springframework.cloud.zookeeper.discovery.DependencyPathUtils. * Representation of this service's dependencies in Zookeeper. * * @author Marcin Grzejszczak + * @author Olga Maciaszek-Sharma * @since 1.0.0 */ @ConfigurationProperties("spring.cloud.zookeeper") @@ -46,17 +46,11 @@ public class ZookeeperDependencies { private String prefix = ""; /** - * Mapping of alias to ZookeeperDependency. From Ribbon perspective the alias is - * actually serviceID since Ribbon can't accept nested structures in serviceID. + * Mapping of alias to ZookeeperDependency. From LoadBalancer perspective the alias is + * actually serviceID since SC LoadBalancer can't accept nested structures in serviceID. */ private Map dependencies = new LinkedHashMap<>(); - /** - * Default health endpoint that will be checked to verify that a dependency is alive. - */ - @Value("${spring.cloud.zookeeper.dependency.ribbon.loadbalancer.defaulthealthendpoint:/health}") - private String defaultHealthEndpoint; - @PostConstruct public void init() { if (StringUtils.hasText(this.prefix)) { @@ -153,10 +147,6 @@ public class ZookeeperDependencies { return this.dependencies; } - public String getDefaultHealthEndpoint() { - return this.defaultHealthEndpoint; - } - public void setPrefix(String prefix) { this.prefix = prefix; } @@ -165,17 +155,11 @@ public class ZookeeperDependencies { this.dependencies = dependencies; } - public void setDefaultHealthEndpoint(String defaultHealthEndpoint) { - this.defaultHealthEndpoint = defaultHealthEndpoint; - } - @Override public String toString() { final StringBuffer sb = new StringBuffer("ZookeeperDependencies{"); sb.append("prefix='").append(this.prefix).append('\''); sb.append(", dependencies=").append(this.dependencies); - sb.append(", defaultHealthEndpoint='").append(this.defaultHealthEndpoint) - .append('\''); sb.append('}'); return sb.toString(); } diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesAutoConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesAutoConfiguration.java index 6c01b51f..30c3eb57 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesAutoConfiguration.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesAutoConfiguration.java @@ -28,12 +28,12 @@ import org.springframework.context.annotation.Configuration; * Provides AutoConfiguration for Zookeeper dependency set up in properties. * * @author Marcin Grzejszczak + * @author Olga Maciaszek-Sharma * @since 1.0.0 */ @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties @ConditionalOnZookeeperEnabled -@ConditionalOnDependenciesPassed @AutoConfigureAfter(ZookeeperAutoConfiguration.class) public class ZookeeperDependenciesAutoConfiguration { diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependency.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependency.java index 012fa647..d2a06be5 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependency.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependency.java @@ -29,6 +29,7 @@ import static java.util.Collections.singletonList; * * @author Marcin Grzejszczak * @author Spencer Gibb + * @author Olga Maciaszek-Sharma * @since 1.0.0 */ public class ZookeeperDependency { @@ -43,11 +44,6 @@ public class ZookeeperDependency { */ private String path; - /** - * Type of load balancer that should be used for this particular dependency. - */ - private LoadBalancerType loadBalancerType = LoadBalancerType.ROUND_ROBIN; - /** * Content type template with {@code $version} placeholder which will be filled by the * {@link ZookeeperDependency#version} variable. @@ -89,11 +85,9 @@ public class ZookeeperDependency { public ZookeeperDependency() { } - public ZookeeperDependency(String path, LoadBalancerType loadBalancerType, - String contentTypeTemplate, String version, + public ZookeeperDependency(String path, String contentTypeTemplate, String version, Map> headers, boolean required, String stubs) { this.path = path; - this.loadBalancerType = loadBalancerType; this.contentTypeTemplate = contentTypeTemplate; this.version = version; this.headers = headers; @@ -182,10 +176,6 @@ public class ZookeeperDependency { return this.path; } - public LoadBalancerType getLoadBalancerType() { - return this.loadBalancerType; - } - public String getContentTypeTemplate() { return this.contentTypeTemplate; } @@ -214,10 +204,6 @@ public class ZookeeperDependency { this.path = path; } - public void setLoadBalancerType(LoadBalancerType loadBalancerType) { - this.loadBalancerType = loadBalancerType; - } - public void setContentTypeTemplate(String contentTypeTemplate) { this.contentTypeTemplate = contentTypeTemplate; } @@ -246,7 +232,6 @@ public class ZookeeperDependency { public String toString() { final StringBuffer sb = new StringBuffer("ZookeeperDependency{"); sb.append("path='").append(this.path).append('\''); - sb.append(", loadBalancerType=").append(this.loadBalancerType); sb.append(", contentTypeTemplate='").append(this.contentTypeTemplate) .append('\''); sb.append(", version='").append(this.version).append('\''); diff --git a/spring-cloud-zookeeper-discovery/src/main/resources/META-INF/spring.factories b/spring-cloud-zookeeper-discovery/src/main/resources/META-INF/spring.factories index 5caf8bbb..00d5a830 100644 --- a/spring-cloud-zookeeper-discovery/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-zookeeper-discovery/src/main/resources/META-INF/spring.factories @@ -1,6 +1,7 @@ # Auto Configuration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryAutoConfiguration,\ +org.springframework.cloud.zookeeper.discovery.dependency.DependencyFeignClientAutoConfiguration,\ org.springframework.cloud.zookeeper.discovery.dependency.DependencyRestTemplateAutoConfiguration,\ org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependenciesAutoConfiguration,\ org.springframework.cloud.zookeeper.discovery.watcher.DependencyWatcherAutoConfiguration,\ @@ -8,8 +9,8 @@ org.springframework.cloud.zookeeper.serviceregistry.ZookeeperAutoServiceRegistra org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistryAutoConfiguration,\ org.springframework.cloud.zookeeper.support.CuratorServiceDiscoveryAutoConfiguration,\ org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryClientConfiguration, \ +org.springframework.cloud.zookeeper.discovery.LoadBalancerZookeeperAutoConfiguration, \ org.springframework.cloud.zookeeper.discovery.reactive.ZookeeperReactiveDiscoveryClientConfiguration -# org.springframework.cloud.zookeeper.discovery.dependency.DependencyFeignClientAutoConfiguration,\ # Environment Post Processors org.springframework.boot.env.EnvironmentPostProcessor=\ diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryAutoRegistrationFalseTests.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryAutoRegistrationFalseTests.java index 6d69f1d8..8d9772ec 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryAutoRegistrationFalseTests.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryAutoRegistrationFalseTests.java @@ -32,17 +32,15 @@ import org.springframework.cloud.client.discovery.composite.CompositeDiscoveryCl import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Controller; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.web.bind.annotation.RequestMapping; import static org.assertj.core.api.BDDAssertions.then; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; /** * @author Spencer Gibb + * @author Olga Maciaszek-Sharma */ @RunWith(SpringRunner.class) @SpringBootTest(classes = ZookeeperDiscoveryAutoRegistrationFalseTests.Config.class, properties = { @@ -85,15 +83,4 @@ public class ZookeeperDiscoveryAutoRegistrationFalseTests { } - @Controller - @Profile("ribbon") - class PingController { - - @RequestMapping("/ping") - String ping() { - return "pong"; - } - - } - } diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests.java index b4a0cdd6..9c58de61 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests.java @@ -110,7 +110,7 @@ public class ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests { } @Bean - TestLoadBalancedClient testRibbonClient(@LoadBalanced RestTemplate restTemplate, + TestLoadBalancedClient testLoadBalancedClient(@LoadBalanced RestTemplate restTemplate, @Value("${spring.application.name}") String springAppName) { return new TestLoadBalancedClient(restTemplate, springAppName); } diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoverySecurePortTests.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoverySecurePortTests.java index 0563e900..8d62d2e3 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoverySecurePortTests.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoverySecurePortTests.java @@ -45,7 +45,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen "feign.hystrix.enabled=false", "spring.cloud.zookeeper.discovery.uriSpec={scheme}://{address}:{port}/contextPath", "spring.cloud.zookeeper.discovery.instance-ssl-port=8443" }, webEnvironment = RANDOM_PORT) -@ActiveProfiles("ribbon") +@ActiveProfiles("loadbalancer") @DirtiesContext public class ZookeeperDiscoverySecurePortTests { @@ -73,7 +73,7 @@ public class ZookeeperDiscoverySecurePortTests { @Configuration @EnableAutoConfiguration @Import(CommonTestConfig.class) - @Profile("ribbon") + @Profile("loadbalancer") static class Config { } diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryTests.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryTests.java index 6f86e8a1..e98176d5 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryTests.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryTests.java @@ -59,10 +59,9 @@ import static org.springframework.cloud.zookeeper.discovery.test.TestLoadBalance */ @RunWith(SpringRunner.class) @SpringBootTest(classes = ZookeeperDiscoveryTests.Config.class, properties = { - "feign.hystrix.enabled=false", "spring.cloud.zookeeper.discovery.uri-spec={scheme}://{address}:{port}/contextPath", "management.endpoints.web.exposure.include=*" }, webEnvironment = RANDOM_PORT) -@ActiveProfiles("ribbon") +@ActiveProfiles("loadbalancer") @DirtiesContext public class ZookeeperDiscoveryTests { @@ -85,7 +84,7 @@ public class ZookeeperDiscoveryTests { Registration registration; @Test - public void should_find_the_app_by_its_name_via_Ribbon() { + public void should_find_the_app_by_its_name_via_LoadBalancer() { // expect: then(registeredServiceStatusViaServiceName()).isEqualTo("UP"); } @@ -98,12 +97,12 @@ public class ZookeeperDiscoveryTests { ServiceInstance instance = instances.get(0); // expect: then(registeredServiceStatus(instance)).isEqualTo("UP"); - then(instance.getInstanceId()).isEqualTo("ribbon-instance-id-123"); + then(instance.getInstanceId()).isEqualTo("loadbalancer-instance-id-123"); then(instance.getMetadata().get("testMetadataKey")) .isEqualTo("testMetadataValue"); then(instance).isInstanceOf(ZookeeperServiceInstance.class); ZookeeperServiceInstance zkInstance = (ZookeeperServiceInstance) instance; - then(zkInstance.getServiceInstance().getId()).isEqualTo("ribbon-instance-id-123"); + then(zkInstance.getServiceInstance().getId()).isEqualTo("loadbalancer-instance-id-123"); } @Test @@ -148,7 +147,7 @@ public class ZookeeperDiscoveryTests { .isEqualTo(this.registration.getHost()); } - @FeignClient("ribbonApp") + @FeignClient("loadBalancerApp") public interface IdUsingFeignClient { @RequestMapping(method = RequestMethod.GET, value = "/hi") @@ -160,12 +159,12 @@ public class ZookeeperDiscoveryTests { @EnableAutoConfiguration @Import(CommonTestConfig.class) @EnableFeignClients(clients = { IdUsingFeignClient.class }) - @Profile("ribbon") + @Profile("loadbalancer") @RestController static class Config { @Bean - TestLoadBalancedClient testRibbonClient(@LoadBalanced RestTemplate restTemplate, + TestLoadBalancedClient testLoadBalancedClient(@LoadBalanced RestTemplate restTemplate, @Value("${spring.application.name}") String springAppName) { return new TestLoadBalancedClient(restTemplate, springAppName); } @@ -178,7 +177,7 @@ public class ZookeeperDiscoveryTests { } @Controller - @Profile("ribbon") + @Profile("loadbalancer") class PingController { @RequestMapping("/ping") diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeprDiscoveryNonWebAppTests.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeprDiscoveryNonWebAppTests.java index 4a77599f..a6632a67 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeprDiscoveryNonWebAppTests.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/ZookeeprDiscoveryNonWebAppTests.java @@ -64,8 +64,7 @@ public class ZookeeprDiscoveryNonWebAppTests { } @Test - public void should_work_when_using_web_client_without_the_web_environment() - throws Exception { + public void should_work_when_using_web_client_without_the_web_environment() { SpringApplication producerApp = new SpringApplicationBuilder(HelloProducer.class) .web(WebApplicationType.SERVLET).build(); SpringApplication clientApplication = new SpringApplicationBuilder( diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyConfig.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyConfig.java index 2e5f2618..8e4d2910 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyConfig.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/DependencyConfig.java @@ -45,7 +45,7 @@ import static org.assertj.core.api.BDDAssertions.then; public class DependencyConfig { @Bean - TestLoadBalancedClient testRibbonClient(@LoadBalanced RestTemplate restTemplate) { + TestLoadBalancedClient testLoadBalancedClient(@LoadBalanced RestTemplate restTemplate) { return new TestLoadBalancedClient(restTemplate); } diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/StickyRuleTests.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/StickyRuleTests.java deleted file mode 100644 index ce064abb..00000000 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/StickyRuleTests.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2015-2019 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 - * - * https://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.zookeeper.discovery.dependency; - -import java.net.URI; -import java.util.List; -import java.util.concurrent.Callable; - -import com.jayway.awaitility.Awaitility; -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.test.TestingServer; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.loadbalancer.LoadBalanced; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import org.springframework.cloud.zookeeper.ZookeeperProperties; -import org.springframework.cloud.zookeeper.discovery.TestServiceRegistrar; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.SocketUtils; -import org.springframework.web.client.RestTemplate; - -/** - * @author Marcin Grzejszczak - */ -@RunWith(SpringRunner.class) -@SpringBootTest(classes = StickyRuleTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles("loadbalancerclient") -public class StickyRuleTests { - - @Autowired - LoadBalancerClient loadBalancerClient; - - @Autowired - DiscoveryClient discoveryClient; - - @Test - @Ignore // FIXME: 3.0.0 - public void should_use_sticky_load_balancing_strategy_taken_from_Zookeeper_dependencies() { - // given: - System.setProperty( - "spring.cloud.zookeeper.dependency.ribbon.loadbalancer.checkping", - "false"); - // expect: - thereAreTwoRegisteredServices(); - URI uri = getUriForAlias(); - Awaitility.await().until(uriMatchesTwice(uri)); - } - - private Callable uriMatchesTwice(final URI uri) { - return new Callable() { - @Override - public Boolean call() throws Exception { - return uriMatches() && uriMatches(); - } - - private boolean uriMatches() { - return uri != null && uri.equals(getUriForAlias()); - } - }; - } - - private boolean thereAreTwoRegisteredServices() { - List instances = this.discoveryClient.getInstances("someAlias"); - return instances != null && instances.size() == 2; - } - - private URI getUriForAlias() { - ServiceInstance alias = this.loadBalancerClient.choose("someAlias"); - return alias != null ? alias.getUri() : null; - } - - @Configuration - @EnableAutoConfiguration - @Profile("loadbalancerclient") - static class Config { - - @Bean - @LoadBalanced - RestTemplate loadBalancedRestTemplate() { - return new RestTemplate(); - } - - @Bean(destroyMethod = "close") - TestingServer testingServer() throws Exception { - return new TestingServer(SocketUtils.findAvailableTcpPort()); - } - - @Bean - ZookeeperProperties zookeeperProperties() throws Exception { - ZookeeperProperties zookeeperProperties = new ZookeeperProperties(); - zookeeperProperties - .setConnectString("localhost:" + testingServer().getPort()); - return zookeeperProperties; - } - - @Bean(initMethod = "start", destroyMethod = "stop") - TestServiceRegistrar serviceOne(CuratorFramework curatorFramework) { - return new TestServiceRegistrar(SocketUtils.findAvailableTcpPort(), - curatorFramework); - } - - @Bean(initMethod = "start", destroyMethod = "stop") - TestServiceRegistrar serviceTwo(CuratorFramework curatorFramework) { - return new TestServiceRegistrar(SocketUtils.findAvailableTcpPort(), - curatorFramework); - } - - } - -} diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesTests.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesTests.java index e4a56e2f..5a0563d8 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesTests.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesTests.java @@ -32,14 +32,14 @@ import static org.assertj.core.api.BDDAssertions.then; public class ZookeeperDependenciesTests { private static final ZookeeperDependency EXPECTED_DEPENDENCY = new ZookeeperDependency( - "path", LoadBalancerType.RANDOM, "contentTypeTemplate", "version", + "path", "contentTypeTemplate", "version", defaultHeader(), false, ""); private static final Map DEPENDENCIES = defaultDependencies(); private static Map> defaultHeader() { return Collections.singletonMap("header", - (Collection) Collections.singletonList("value")); + Collections.singletonList("value")); } private static Map defaultDependencies() { diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDependenciesIntegrationTests.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDependenciesIntegrationTests.java index e92fde70..bbe66dad 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDependenciesIntegrationTests.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDependenciesIntegrationTests.java @@ -17,7 +17,6 @@ package org.springframework.cloud.zookeeper.discovery.dependency; import java.util.List; -import java.util.concurrent.Callable; import org.junit.Ignore; import org.junit.Test; @@ -41,11 +40,12 @@ import static org.springframework.cloud.zookeeper.discovery.test.TestLoadBalance /** * @author Marcin Grzejszczak + * @author Olga Maciaszek-Sharma */ @RunWith(SpringRunner.class) @SpringBootTest(classes = ZookeeperDiscoveryWithDependenciesIntegrationTests.Config.class, properties = { - "feign.hystrix.enabled=false", "debug=true", - "management.endpoints.web.exposure.include=*" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) + "debug=true", + "management.endpoints.web.exposure.include=*"}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles("dependencies") public class ZookeeperDiscoveryWithDependenciesIntegrationTests { @@ -69,12 +69,7 @@ public class ZookeeperDiscoveryWithDependenciesIntegrationTests { // given: final DiscoveryClient discoveryClient = this.discoveryClient; // expect: - await().until(new Callable() { - @Override - public Boolean call() throws Exception { - return !discoveryClient.getInstances("nameWithoutAlias").isEmpty(); - } - }); + await().until(() -> !discoveryClient.getInstances("nameWithoutAlias").isEmpty()); } @Test @@ -94,12 +89,9 @@ public class ZookeeperDiscoveryWithDependenciesIntegrationTests { // given: final IdUsingFeignClient idUsingFeignClient = this.idUsingFeignClient; // expect: - await().until(new Callable() { - @Override - public Boolean call() throws Exception { - then(idUsingFeignClient.getBeans()).isNotEmpty(); - return true; - } + await().until(() -> { + then(idUsingFeignClient.getBeans()).isNotEmpty(); + return true; }); } @@ -107,12 +99,7 @@ public class ZookeeperDiscoveryWithDependenciesIntegrationTests { @Test public void should_find_a_collaborator_via_load_balanced_rest_template_by_using_its_alias_from_dependencies() { // expect: - await().until(new Callable() { - @Override - public Boolean call() throws Exception { - return callingServiceAtBeansEndpointIsNotEmpty(); - } - }); + await().until(() -> callingServiceAtBeansEndpointIsNotEmpty()); } @Ignore // FIXME 2.0.0 @@ -121,24 +108,18 @@ public class ZookeeperDiscoveryWithDependenciesIntegrationTests { // given: final AliasUsingFeignClient aliasUsingFeignClient = this.aliasUsingFeignClient; // expect: - await().until(new Callable() { - @Override - public Boolean call() throws Exception { - then(aliasUsingFeignClient.getBeans()).isNotEmpty(); - return true; - } + await().until(() -> { + then(aliasUsingFeignClient.getBeans()).isNotEmpty(); + return true; }); } @Test public void should_have_headers_from_dependencies_attached_to_the_request_via_load_balanced_rest_template() { // expect: - await().until(new Callable() { - @Override - public Boolean call() throws Exception { - callingServiceToCheckIfHeadersArePassed(); - return true; - } + await().until(() -> { + callingServiceToCheckIfHeadersArePassed(); + return true; }); } @@ -148,12 +129,9 @@ public class ZookeeperDiscoveryWithDependenciesIntegrationTests { // given: final AliasUsingFeignClient aliasUsingFeignClient = this.aliasUsingFeignClient; // expect: - await().until(new Callable() { - @Override - public Boolean call() throws Exception { - aliasUsingFeignClient.checkHeaders(); - return true; - } + await().until(() -> { + aliasUsingFeignClient.checkHeaders(); + return true; }); } @@ -164,12 +142,7 @@ public class ZookeeperDiscoveryWithDependenciesIntegrationTests { List instances = discoveryClient.getInstances("someAlias"); final ServiceInstance instance = instances.get(0); // expect: - await().until(new Callable() { - @Override - public Boolean call() throws Exception { - return callingServiceViaUrlOnBeansEndpointIsNotEmpty(instance); - } - }); + await().until(() -> callingServiceViaUrlOnBeansEndpointIsNotEmpty(instance)); } @Test diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesTests.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesTests.java index c731b32f..483f15c9 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesTests.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesTests.java @@ -50,7 +50,7 @@ public class ZookeeperDiscoveryWithDyingDependenciesTests { // Issue: #45 @Test - public void should_refresh_a_dependency_in_Ribbon_when_the_dependency_has_deregistered_and_registered_in_Zookeeper() + public void should_refresh_a_dependency_in_LoadBalancer_when_the_dependency_has_deregistered_and_registered_in_Zookeeper() throws Exception { ConfigurableApplicationContext serverContext = null; ConfigurableApplicationContext clientContext = null; diff --git a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/test/CommonTestConfig.java b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/test/CommonTestConfig.java index 6280f0d1..5db6f6b8 100644 --- a/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/test/CommonTestConfig.java +++ b/spring-cloud-zookeeper-discovery/src/test/java/org/springframework/cloud/zookeeper/discovery/test/CommonTestConfig.java @@ -43,8 +43,7 @@ public class CommonTestConfig { } @Bean - ZookeeperProperties zookeeperProperties(TestingServer testingServer) - throws Exception { + ZookeeperProperties zookeeperProperties(TestingServer testingServer) { ZookeeperProperties zookeeperProperties = new ZookeeperProperties(); zookeeperProperties.setConnectString("localhost:" + testingServer.getPort()); return zookeeperProperties; diff --git a/spring-cloud-zookeeper-discovery/src/test/resources/application-ribbon.yml b/spring-cloud-zookeeper-discovery/src/test/resources/application-loadbalancer.yml similarity index 79% rename from spring-cloud-zookeeper-discovery/src/test/resources/application-ribbon.yml rename to spring-cloud-zookeeper-discovery/src/test/resources/application-loadbalancer.yml index 290d0f71..0971738a 100644 --- a/spring-cloud-zookeeper-discovery/src/test/resources/application-ribbon.yml +++ b/spring-cloud-zookeeper-discovery/src/test/resources/application-loadbalancer.yml @@ -1,13 +1,13 @@ spring: application: - name: ribbonApp + name: loadBalancerApp cloud: zookeeper: discovery: metadata: testMetadataKey: testMetadataValue uriSpec: "{scheme}://{address}:{port}/contextPath" - instance-id: ribbon-instance-id-123 + instance-id: loadbalancer-instance-id-123 management: security: enabled: false diff --git a/spring-cloud-zookeeper-discovery/src/test/resources/application.yml b/spring-cloud-zookeeper-discovery/src/test/resources/application.yml index 57500c52..18fc3fee 100644 --- a/spring-cloud-zookeeper-discovery/src/test/resources/application.yml +++ b/spring-cloud-zookeeper-discovery/src/test/resources/application.yml @@ -1,4 +1,4 @@ -testInstance.ribbon.ServerListRefreshInterval: 100 +testInstance.loadbalancer.ServerListRefreshInterval: 100 logging: level: org.apache.zookeeper.ClientCnxn: ERROR \ No newline at end of file