diff --git a/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/config/GatewayMetricsAutoConfiguration.java b/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/config/GatewayMetricsAutoConfiguration.java index 708fb8a459..606cc6a06f 100644 --- a/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/config/GatewayMetricsAutoConfiguration.java +++ b/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/config/GatewayMetricsAutoConfiguration.java @@ -31,11 +31,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.metrics.autoconfigure.CompositeMeterRegistryAutoConfiguration; -import org.springframework.boot.metrics.autoconfigure.MetricsAutoConfiguration; -import org.springframework.boot.observation.autoconfigure.ObservationAutoConfiguration; -import org.springframework.boot.tracing.autoconfigure.MicrometerTracingAutoConfiguration; -import org.springframework.boot.tracing.autoconfigure.TracingProperties; +import org.springframework.boot.micrometer.metrics.autoconfigure.CompositeMeterRegistryAutoConfiguration; +import org.springframework.boot.micrometer.metrics.autoconfigure.MetricsAutoConfiguration; +import org.springframework.boot.micrometer.observation.autoconfigure.ObservationAutoConfiguration; +import org.springframework.boot.micrometer.tracing.autoconfigure.MicrometerTracingAutoConfiguration; +import org.springframework.boot.micrometer.tracing.autoconfigure.TracingProperties; import org.springframework.boot.webflux.autoconfigure.HttpHandlerAutoConfiguration; import org.springframework.cloud.gateway.filter.GatewayMetricsFilter; import org.springframework.cloud.gateway.filter.headers.observation.GatewayObservationConvention; diff --git a/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/route/CachingRouteLocator.java b/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/route/CachingRouteLocator.java index 5cf8cdae39..178103f41d 100644 --- a/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/route/CachingRouteLocator.java +++ b/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/route/CachingRouteLocator.java @@ -16,6 +16,8 @@ package org.springframework.cloud.gateway.route; +import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -88,8 +90,12 @@ public void onApplicationEvent(RefreshRoutesEvent event) { final Mono> scopedRoutes = fetch(event.getMetadata()).collect(Collectors.toList()) .onErrorResume(s -> Mono.just(List.of())); + Map routeIdToIdxMap = new HashMap<>(); + getRoutes().index().subscribe(t -> routeIdToIdxMap.put(t.getT2().getId(), t.getT1())); + scopedRoutes.subscribe(scopedRoutesList -> { updateCache(Flux.concat(Flux.fromIterable(scopedRoutesList), getNonScopedRoutes(event)) + .sort(Comparator.comparing(r -> routeIdToIdxMap.getOrDefault(r.getId(), Long.MIN_VALUE))) .sort(AnnotationAwareOrderComparator.INSTANCE)); }, this::handleRefreshError); } diff --git a/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java b/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java index 09d1167da2..10a27efef9 100644 --- a/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java +++ b/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java @@ -44,8 +44,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.ssl.SslBundleRegistrar; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.metrics.autoconfigure.MetricsAutoConfiguration; -import org.springframework.boot.metrics.autoconfigure.export.simple.SimpleMetricsExportAutoConfiguration; +import org.springframework.boot.micrometer.metrics.autoconfigure.MetricsAutoConfiguration; +import org.springframework.boot.micrometer.metrics.autoconfigure.export.simple.SimpleMetricsExportAutoConfiguration; import org.springframework.boot.security.autoconfigure.reactive.ReactiveSecurityAutoConfiguration; import org.springframework.boot.security.oauth2.client.autoconfigure.reactive.ReactiveOAuth2ClientAutoConfiguration; import org.springframework.boot.ssl.DefaultSslBundleRegistry; diff --git a/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/route/CachingRouteLocatorTests.java b/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/route/CachingRouteLocatorTests.java index d5609ea847..58862704bd 100644 --- a/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/route/CachingRouteLocatorTests.java +++ b/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/route/CachingRouteLocatorTests.java @@ -17,7 +17,9 @@ package org.springframework.cloud.gateway.route; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -117,6 +119,23 @@ else if (i == 2) { } + @Test + public void updateScopedRoutes() { + Map metadata = Map.of("metadata-key1", "metadata-value1"); + int order = 0; + Route route1 = route(1, order, Collections.EMPTY_MAP); + Route route2 = route(2, order, metadata); + CachingRouteLocator locator = new CachingRouteLocator(() -> Flux.just(route1, route2)); + + List routes = locator.getRoutes().collectList().block(); + assertThat(routes).containsExactly(route1, route2); + + RefreshRoutesEvent event = new RefreshRoutesEvent(this, metadata); + locator.onApplicationEvent(event); + routes = locator.getRoutes().collectList().block(); + assertThat(routes).containsExactly(route1, route2); + } + private void waitUntilRefreshFinished(CachingRouteLocator locator, List resultEvents) throws InterruptedException { CountDownLatch cdl = new CountDownLatch(1); @@ -129,6 +148,16 @@ private void waitUntilRefreshFinished(CachingRouteLocator locator, List metadata) { + return Route.async() + .id(String.valueOf(id)) + .uri("http://localhost/" + id) + .order(order) + .predicate(exchange -> true) + .metadata(metadata) + .build(); + } + Route route(int id) { return Route.async() .id(String.valueOf(id))