From 9557d12253cf2759245fdbbc2f86f6a4974bef3d Mon Sep 17 00:00:00 2001 From: zhengchao <2923289118@qq.com> Date: Thu, 27 Oct 2022 04:12:49 +0800 Subject: [PATCH 1/3] Adds sorted filter cache switch. Fixes gh-2760 Fixes gh-2756 --- .../gateway/config/GatewayProperties.java | 17 ++++++++- .../gateway/handler/FilteringWebHandler.java | 35 +++++++++++++++---- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java index 53ea714c..bb117219 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java @@ -68,6 +68,21 @@ public class GatewayProperties { */ private boolean failOnRouteDefinitionError = true; + /** + * org.springframework.cloud.gateway.handler.FilteringWebHandler#handle add filter cache + * if true then enable filter cache + */ + private boolean filterCache = false; + + public boolean isFilterCache() { + return filterCache; + } + + public void setFilterCache(boolean filterCache) { + this.filterCache = filterCache; + } + + public List getRoutes() { return routes; } @@ -109,7 +124,7 @@ public class GatewayProperties { .append("defaultFilters", defaultFilters) .append("streamingMediaTypes", streamingMediaTypes) .append("failOnRouteDefinitionError", failOnRouteDefinitionError) - .toString(); + .append("filterCache", filterCache).toString(); } diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java index 395ee027..92a981f2 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java @@ -18,10 +18,12 @@ package org.springframework.cloud.gateway.handler; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.cloud.gateway.config.GatewayProperties; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; @@ -55,8 +57,13 @@ public class FilteringWebHandler implements WebHandler { private final List globalFilters; - public FilteringWebHandler(List globalFilters) { + private ConcurrentHashMap> RouteFilterMap = new ConcurrentHashMap(); + + private GatewayProperties properties; + + public FilteringWebHandler(List globalFilters, GatewayProperties properties) { this.globalFilters = loadFilters(globalFilters); + this.properties = properties; } private static List loadFilters(List filters) { @@ -84,12 +91,7 @@ public class FilteringWebHandler implements WebHandler { @Override public Mono handle(ServerWebExchange exchange) { Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR); - List gatewayFilters = route.getFilters(); - - List combined = new ArrayList<>(this.globalFilters); - combined.addAll(gatewayFilters); - // TODO: needed or cached? - AnnotationAwareOrderComparator.sort(combined); + List combined = getCombinedFilters(route); if (logger.isDebugEnabled()) { logger.debug("Sorted gatewayFilterFactories: " + combined); @@ -98,6 +100,25 @@ public class FilteringWebHandler implements WebHandler { return new DefaultGatewayFilterChain(combined).filter(exchange); } + public List getCombinedFilters(Route route){ + if (this.properties.isFilterCache()) { + if (!this.RouteFilterMap.contains(route)) { + RouteFilterMap.put(route,getAllFilters(route)); + } + return RouteFilterMap.get(route); + }else { + return getAllFilters(route); + } + + } + public List getAllFilters(Route route){ + List gatewayFilters = route.getFilters(); + List combined = new ArrayList<>(this.globalFilters); + combined.addAll(gatewayFilters); + AnnotationAwareOrderComparator.sort(combined); + return combined; + } + private static class DefaultGatewayFilterChain implements GatewayFilterChain { private final int index; From d3823652b289e5afe30565017d4b55dd4708760b Mon Sep 17 00:00:00 2001 From: spencergibb Date: Wed, 13 Nov 2024 12:56:40 -0500 Subject: [PATCH 2/3] Polishes route filter cache. Adds refresh listener to clear the cache. See gh-2760 --- .../config/GatewayAutoConfiguration.java | 4 +- .../gateway/config/GatewayProperties.java | 17 ++- .../gateway/handler/FilteringWebHandler.java | 48 ++++--- .../gateway/route/RouteRefreshListener.java | 7 +- ...ebHandlerCacheEnabledIntegrationTests.java | 123 ++++++++++++++++++ 5 files changed, 168 insertions(+), 31 deletions(-) create mode 100644 spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/FilteringWebHandlerCacheEnabledIntegrationTests.java diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index c1906e3f..956279d1 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -272,8 +272,8 @@ public class GatewayAutoConfiguration { @Bean @ConditionalOnMissingBean - public FilteringWebHandler filteringWebHandler(List globalFilters) { - return new FilteringWebHandler(globalFilters); + public FilteringWebHandler filteringWebHandler(List globalFilters, GatewayProperties properties) { + return new FilteringWebHandler(globalFilters, properties.isRouteFilterCacheEnabled()); } @Bean diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java index bb117219..356185f5 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java @@ -69,20 +69,18 @@ public class GatewayProperties { private boolean failOnRouteDefinitionError = true; /** - * org.springframework.cloud.gateway.handler.FilteringWebHandler#handle add filter cache - * if true then enable filter cache + * Enables the route filter cache, defaults to false. */ - private boolean filterCache = false; + private boolean routeFilterCacheEnabled = false; - public boolean isFilterCache() { - return filterCache; + public boolean isRouteFilterCacheEnabled() { + return routeFilterCacheEnabled; } - public void setFilterCache(boolean filterCache) { - this.filterCache = filterCache; + public void setRouteFilterCacheEnabled(boolean routeFilterCacheEnabled) { + this.routeFilterCacheEnabled = routeFilterCacheEnabled; } - public List getRoutes() { return routes; } @@ -124,7 +122,8 @@ public class GatewayProperties { .append("defaultFilters", defaultFilters) .append("streamingMediaTypes", streamingMediaTypes) .append("failOnRouteDefinitionError", failOnRouteDefinitionError) - .append("filterCache", filterCache).toString(); + .append("routeFilterCacheEnabled", routeFilterCacheEnabled) + .toString(); } diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java index 92a981f2..5ccc4ce1 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java @@ -23,15 +23,16 @@ import java.util.stream.Collectors; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.gateway.config.GatewayProperties; import reactor.core.publisher.Mono; +import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.OrderedGatewayFilter; import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory; import org.springframework.cloud.gateway.route.Route; +import org.springframework.context.ApplicationListener; import org.springframework.core.DecoratingProxy; import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationAwareOrderComparator; @@ -51,19 +52,28 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G * @author Yuxin Wang * @since 0.1 */ -public class FilteringWebHandler implements WebHandler { +public class FilteringWebHandler implements WebHandler, ApplicationListener { protected static final Log logger = LogFactory.getLog(FilteringWebHandler.class); private final List globalFilters; - private ConcurrentHashMap> RouteFilterMap = new ConcurrentHashMap(); + private final ConcurrentHashMap> routeFilterMap = new ConcurrentHashMap(); - private GatewayProperties properties; + private final boolean filterCacheEnabled; - public FilteringWebHandler(List globalFilters, GatewayProperties properties) { + @Deprecated + public FilteringWebHandler(List globalFilters) { + this(globalFilters, false); + } + + public FilteringWebHandler(List globalFilters, boolean filterCacheEnabled) { this.globalFilters = loadFilters(globalFilters); - this.properties = properties; + this.filterCacheEnabled = filterCacheEnabled; + } + + /* for testing */ ConcurrentHashMap> getRouteFilterMap() { + return routeFilterMap; } private static List loadFilters(List filters) { @@ -83,10 +93,12 @@ public class FilteringWebHandler implements WebHandler { }).collect(Collectors.toList()); } - /* - * TODO: relocate @EventListener(RefreshRoutesEvent.class) void handleRefresh() { - * this.combinedFiltersForRoute.clear(); - */ + @Override + public void onApplicationEvent(RefreshRoutesEvent event) { + if (this.filterCacheEnabled) { + routeFilterMap.clear(); + } + } @Override public Mono handle(ServerWebExchange exchange) { @@ -100,18 +112,16 @@ public class FilteringWebHandler implements WebHandler { return new DefaultGatewayFilterChain(combined).filter(exchange); } - public List getCombinedFilters(Route route){ - if (this.properties.isFilterCache()) { - if (!this.RouteFilterMap.contains(route)) { - RouteFilterMap.put(route,getAllFilters(route)); - } - return RouteFilterMap.get(route); - }else { + protected List getCombinedFilters(Route route) { + if (this.filterCacheEnabled) { + return routeFilterMap.computeIfAbsent(route, this::getAllFilters); + } + else { return getAllFilters(route); } - } - public List getAllFilters(Route route){ + + protected List getAllFilters(Route route) { List gatewayFilters = route.getFilters(); List combined = new ArrayList<>(this.globalFilters); combined.addAll(gatewayFilters); diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/RouteRefreshListener.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/RouteRefreshListener.java index ac2309fc..c67d61b9 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/RouteRefreshListener.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/RouteRefreshListener.java @@ -46,7 +46,12 @@ public class RouteRefreshListener implements ApplicationListener r.path("/get").filters(f -> f.prefixPath("/httpbin")).uri("lb://testservice")) + .route("testRoute1", + r -> r.path("/anything/testRoute1") + .filters(f -> f.prefixPath("/httpbin")) + .uri("lb://testservice")) + .build(); + } + + } + +} From 389f950a33f199217363fa43d96b934792941b2f Mon Sep 17 00:00:00 2001 From: spencergibb Date: Thu, 14 Nov 2024 10:56:27 -0500 Subject: [PATCH 3/3] Polishes route filter cache. renames variable, formatting See gh-2760 --- .../cloud/gateway/handler/FilteringWebHandler.java | 10 +++++----- ...ilteringWebHandlerCacheEnabledIntegrationTests.java | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java index 5ccc4ce1..9f3beb37 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java @@ -60,16 +60,16 @@ public class FilteringWebHandler implements WebHandler, ApplicationListener> routeFilterMap = new ConcurrentHashMap(); - private final boolean filterCacheEnabled; + private final boolean routeFilterCacheEnabled; @Deprecated public FilteringWebHandler(List globalFilters) { this(globalFilters, false); } - public FilteringWebHandler(List globalFilters, boolean filterCacheEnabled) { + public FilteringWebHandler(List globalFilters, boolean routeFilterCacheEnabled) { this.globalFilters = loadFilters(globalFilters); - this.filterCacheEnabled = filterCacheEnabled; + this.routeFilterCacheEnabled = routeFilterCacheEnabled; } /* for testing */ ConcurrentHashMap> getRouteFilterMap() { @@ -95,7 +95,7 @@ public class FilteringWebHandler implements WebHandler, ApplicationListener getCombinedFilters(Route route) { - if (this.filterCacheEnabled) { + if (this.routeFilterCacheEnabled) { return routeFilterMap.computeIfAbsent(route, this::getAllFilters); } else { diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/FilteringWebHandlerCacheEnabledIntegrationTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/FilteringWebHandlerCacheEnabledIntegrationTests.java index 87aab806..650a8a08 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/FilteringWebHandlerCacheEnabledIntegrationTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/FilteringWebHandlerCacheEnabledIntegrationTests.java @@ -42,8 +42,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @SpringBootTest(webEnvironment = RANDOM_PORT, - properties = { "spring.cloud.gateway.route-filter-cache-enabled=true", "management.endpoint.gateway.enabled=true", - "management.endpoints.web.exposure.include=*", "spring.cloud.gateway.actuator.verbose.enabled=true" }) + properties = { "spring.cloud.gateway.route-filter-cache-enabled=true", + "management.endpoint.gateway.enabled=true", "management.endpoints.web.exposure.include=*", + "spring.cloud.gateway.actuator.verbose.enabled=true" }) @DirtiesContext public class FilteringWebHandlerCacheEnabledIntegrationTests extends BaseWebClientTests {