Deep Dive into Spring Cloud Gateway: Architecture and Request Flow Explained
This article introduces Spring Cloud Gateway, outlines its core components such as routes, predicates, and filters, and provides a detailed step‑by‑step analysis of the request handling process—including code examples, filter chain execution, routing, and response writing—offering practical insights for backend developers.
Introduction
Spring Cloud Gateway is an API gateway framework launched by Spring, built on Spring 5, Spring Boot 2, Project Reactor, and Netty. It offers a simple yet effective architecture that is worth studying.
Overview
The framework combines routing, predicates, and filters to process incoming requests. Compared with Netflix's Zuul, which originally used a blocking model, Spring Cloud Gateway adopts a non‑blocking reactive approach.
Key Terms
Route : A metadata object that includes URI, predicate, filter, and other attributes.
Predicate : A Java 8 functional interface that determines when a route becomes active.
Filter : The core module that handles circuit breaking, security, logic execution, and network calls. Filters are divided into gateway filters (specific to a route) and global filters (applied to all routes).
Sample Code
@RequestMapping("/paramTest")
public Object paramTest(@RequestParam Map<String,Object> param) {
return param.get("name");
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("path_route", r ->
r.path("/get")
.filters(f -> f.addRequestParameter("name", "value"))
.uri("forward:///paramTest"))
.build();
}The .route method defines a routing rule; .path is a predicate that matches the /get path; .filters adds a request‑parameter filter; .uri determines the target, with forward delegating to Spring MVC.
Request Flow Analysis
1. Accepting the Request
The underlying Netty server forwards the request to ReactorHttpHandlerAdapter, which converts Netty's request/response into HTTP objects for further processing.
@Override
public Mono<Void> apply(HttpServerRequest request, HttpServerResponse response) {
NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(response.alloc());
ServerHttpRequest adaptedRequest = new ReactorServerHttpRequest(request, bufferFactory);
ServerHttpResponse adaptedResponse = new ReactorServerHttpResponse(response, bufferFactory);
return this.httpHandler.handle(adaptedRequest, adaptedResponse)
.doOnError(ex -> logger.warn("Handling completed with error: " + ex.getMessage()))
.doOnSuccess(aVoid -> logger.debug("Handling completed with success"));
}2. Web Filter Chain
The request and response are wrapped into a ServerWebExchange, which is passed through the web filter chain. This chain includes security, logging, and authentication filters, demonstrating the framework’s strong extensibility.
3. Finding the Route
The RoutePredicateHandlerMapping iterates over all route predicates to find a match.
return this.routeLocator.getRoutes()
.filter(route -> route.getPredicate().test(exchange));In this example, the PathRoutePredicateFactory handles the /get path.
4. Core Filter Execution
After locating the route, FilteringWebHandler merges global and route‑specific filters, sorts them, and executes the chain.
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
List<GatewayFilter> gatewayFilters = route.getFilters();
List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
combined.addAll(gatewayFilters);
AnnotationAwareOrderComparator.sort(combined);
return new DefaultGatewayFilterChain(combined).filter(exchange);
}Obtain route‑level filters.
Obtain global filters.
Combine and sort them.
Execute the filter chain.
5. Request Forwarding
The ForwardRoutingFilter forwards the request to Spring MVC's DispatcherHandler based on the forward scheme.
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
String scheme = requestUrl.getScheme();
if (isAlreadyRouted(exchange) || !"forward".equals(scheme)) {
return chain.filter(exchange);
}
setAlreadyRouted(exchange);
return this.dispatcherHandler.handle(exchange);
}6. Response Writing
The NettyWriteResponseFilter writes the response back to the client after all other filters have completed.
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange).then(Mono.defer(() -> {
HttpClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR);
if (clientResponse == null) {
return Mono.empty();
}
ServerHttpResponse response = exchange.getResponse();
NettyDataBufferFactory factory = (NettyDataBufferFactory) response.bufferFactory();
Flux<NettyDataBuffer> body = clientResponse.receive()
.retain()
.map(factory::wrap);
MediaType contentType = response.getHeaders().getContentType();
return (isStreamingMediaType(contentType) ?
response.writeAndFlushWith(body.map(Flux::just)) : response.writeWith(body));
}));
}Conclusion
The most critical design of Spring Cloud Gateway is its filter chain, which essentially makes the framework a filter‑execution engine rather than a simple API gateway. Optimizations can be made in route‑predicate matching for large rule sets, and providing a way to unload unnecessary filters could further improve performance in high‑traffic scenarios.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
