diff --git a/docs/src/main/asciidoc/spring-cloud-gateway.adoc b/docs/src/main/asciidoc/spring-cloud-gateway.adoc index ef59a964..7507e468 100644 --- a/docs/src/main/asciidoc/spring-cloud-gateway.adoc +++ b/docs/src/main/asciidoc/spring-cloud-gateway.adoc @@ -51,6 +51,8 @@ NOTE: URIs defined in routes without a port will get a default port set to 80 an Spring Cloud Gateway matches routes as part of the Spring WebFlux `HandlerMapping` infrastructure. Spring Cloud Gateway includes many built-in Route Predicate Factories. All of these predicates match on different attributes of the HTTP request. Multiple Route Predicate Factories can be combined and are combined via logical `and`. +WARNING: Previously, Spring Cloud Gateway generated a default Route ID by creating a random UUID. Generating a random UUID is a blocking operation and can lead to instability. Default id generation has been turned off by default. To re-enable this set an environment variable `SPRING_CLOUD_GATEWAY_ROUTE_GENERATE_ID` or system property `spring.cloud.gateway.route.generate-id` to `true`. + === After Route Predicate Factory The After Route Predicate Factory takes one parameter, a datetime. This predicate matches requests that happen after the current datetime. diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteDefinitionLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteDefinitionLocator.java index a1017b02..fbef41b6 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteDefinitionLocator.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteDefinitionLocator.java @@ -16,52 +16,22 @@ package org.springframework.cloud.gateway.route; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; - -import org.springframework.util.AlternativeJdkIdGenerator; -import org.springframework.util.IdGenerator; /** * @author Spencer Gibb */ public class CompositeRouteDefinitionLocator implements RouteDefinitionLocator { - private static final Log log = LogFactory - .getLog(CompositeRouteDefinitionLocator.class); - private final Flux delegates; - private final IdGenerator idGenerator; - public CompositeRouteDefinitionLocator(Flux delegates) { - this(delegates, new AlternativeJdkIdGenerator()); - } - - public CompositeRouteDefinitionLocator(Flux delegates, - IdGenerator idGenerator) { this.delegates = delegates; - this.idGenerator = idGenerator; } @Override public Flux getRouteDefinitions() { - return this.delegates.flatMap(RouteDefinitionLocator::getRouteDefinitions) - .flatMap(routeDefinition -> Mono.justOrEmpty(routeDefinition.getId()) - .defaultIfEmpty(idGenerator.generateId().toString()) - .publishOn(Schedulers.elastic()).map(id -> { - if (routeDefinition.getId() == null) { - routeDefinition.setId(id); - if (log.isDebugEnabled()) { - log.debug( - "Id set on route definition: " + routeDefinition); - } - } - return routeDefinition; - })); + return this.delegates.flatMap(RouteDefinitionLocator::getRouteDefinitions); } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinition.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinition.java index ba7b699c..d35a1665 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinition.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinition.java @@ -20,6 +20,7 @@ import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.UUID; import javax.validation.Valid; import javax.validation.ValidationException; @@ -38,6 +39,7 @@ import static org.springframework.util.StringUtils.tokenizeToStringArray; @Validated public class RouteDefinition { + @NotEmpty private String id; @NotEmpty @@ -53,6 +55,13 @@ public class RouteDefinition { private int order = 0; public RouteDefinition() { + String envGenerateId = System.getenv("SPRING_CLOUD_GATEWAY_ROUTE_GENERATE_ID"); + String propGenerateId = System + .getProperty("spring.cloud.gateway.route.generate-id", "false"); + if ("true".equalsIgnoreCase(envGenerateId) + || "true".equalsIgnoreCase(propGenerateId)) { + id = UUID.randomUUID().toString(); + } } public RouteDefinition(String text) { diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionDefaultIdTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionDefaultIdTests.java index 8e28bad5..b68b1ffc 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionDefaultIdTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionDefaultIdTests.java @@ -16,6 +16,8 @@ package org.springframework.cloud.gateway.route; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -43,6 +45,16 @@ public class RouteDefinitionDefaultIdTests { @Autowired private GatewayProperties properties; + @BeforeClass + public static void before() { + System.setProperty("spring.cloud.gateway.route.generate-id", "true"); + } + + @AfterClass + public static void after() { + System.clearProperty("spring.cloud.gateway.route.generate-id"); + } + @Test public void testDefaultIdWorks() { assertThat(properties.getRoutes()).hasSize(1);