From e960eadb3254df00760646ac57ca9b0b1d2a50d9 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Mon, 28 Jan 2019 15:05:19 -0500 Subject: [PATCH] WeightCalculatorWebFilter now forces subscription of RouteLocator. Because it needs to calculate the weights before predicates run, if the predicates are all defined in yaml, weights aren't initialized until after the first run, meaning weights are unavailable in the predicates. WeightCalculatorWebFilter now listens for RoutesRefreshedEvent. When triggered, it subscribes to RouteLocator, forcing initialization. fixes gh-332 --- .../config/GatewayAutoConfiguration.java | 4 +- .../filter/WeightCalculatorWebFilter.java | 23 ++++-- .../WeightRoutePredicateFactory.java | 2 + ...ightRoutePredicateFactoryYaml404Tests.java | 81 +++++++++++++++++++ .../resources/application-weights-404.yml | 22 +++++ 5 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactoryYaml404Tests.java create mode 100644 spring-cloud-gateway-core/src/test/resources/application-weights-404.yml diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index 0bc5a710..907420da 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -392,8 +392,8 @@ public class GatewayAutoConfiguration { } @Bean - public WeightCalculatorWebFilter weightCalculatorWebFilter(Validator validator) { - return new WeightCalculatorWebFilter(validator); + public WeightCalculatorWebFilter weightCalculatorWebFilter(Validator validator, ObjectProvider routeLocator) { + return new WeightCalculatorWebFilter(validator, routeLocator); } /*@Bean diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WeightCalculatorWebFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WeightCalculatorWebFilter.java index 0868e438..72f8d567 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WeightCalculatorWebFilter.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WeightCalculatorWebFilter.java @@ -27,9 +27,13 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.jetbrains.annotations.NotNull; +import reactor.core.publisher.Mono; + +import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.gateway.event.PredicateArgsEvent; +import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.event.WeightDefinedEvent; +import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.support.ConfigurationUtils; import org.springframework.cloud.gateway.support.WeightConfig; import org.springframework.context.ApplicationEvent; @@ -43,8 +47,6 @@ import org.springframework.web.server.WebFilterChain; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.WEIGHT_ATTR; -import reactor.core.publisher.Mono; - /** * @author Spencer Gibb */ @@ -55,17 +57,24 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli public static final int WEIGHT_CALC_FILTER_ORDER = 10001; private final Validator validator; + private final ObjectProvider routeLocator; private Random random = new Random(); private int order = WEIGHT_CALC_FILTER_ORDER; private Map groupWeights = new ConcurrentHashMap<>(); /* for testing */ WeightCalculatorWebFilter() { - this(null); + this(null, null); } + @Deprecated public WeightCalculatorWebFilter(Validator validator) { + this(validator, null); + } + + public WeightCalculatorWebFilter(Validator validator, ObjectProvider routeLocator) { this.validator = validator; + this.routeLocator = routeLocator; } @Override @@ -84,7 +93,8 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli @Override public boolean supportsEventType(Class eventType) { return PredicateArgsEvent.class.isAssignableFrom(eventType) || // config file - WeightDefinedEvent.class.isAssignableFrom(eventType); // java dsl + WeightDefinedEvent.class.isAssignableFrom(eventType) || // java dsl + RefreshRoutesEvent.class.isAssignableFrom(eventType); // force initialization } @Override @@ -98,6 +108,8 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli handle((PredicateArgsEvent) event); } else if (event instanceof WeightDefinedEvent) { addWeightConfig(((WeightDefinedEvent)event).getWeightConfig()); + } else if (event instanceof RefreshRoutesEvent && routeLocator != null) { + routeLocator.ifAvailable(locator -> locator.getRoutes().subscribe()); // forces initialization } } @@ -197,7 +209,6 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli return chain.filter(exchange); } - @NotNull /* for testing */ static Map getWeights(ServerWebExchange exchange) { Map weights = exchange.getAttribute(WEIGHT_ATTR); diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactory.java index 5d41d33c..4ccd3a48 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactory.java @@ -92,6 +92,8 @@ public class WeightRoutePredicateFactory extends AbstractRoutePredicateFactory