摘要:本篇文章主要从源码的角度揭秘Spring Cloud Gateway的怎么处理请求流程。

1.Spring Gateway概述

Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代Netflix ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。

2. Spring Cloud gateway请求入口分析

不管是Zuul,还是Spring Cloud Gateway还是基于Netty的自研网关,都会把请求进来的Request,或者返回的Response进行包装,转换提取为网关运行的上下文信息,而在Spring Cloud gateway中网关的上下文为ServerWebExchange。

2.1 入口HttpServerRequest和HttpServerResponse转换

Spring Cloud Gateway的请求入口,org.springframework.http.server.reactive.ReactorHttpHandlerAdapter#apply方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Override
public Mono<Void> apply(HttpServerRequest request, HttpServerResponse response) {

NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(response.alloc());
ServerHttpRequest adaptedRequest;
ServerHttpResponse adaptedResponse;
try {
adaptedRequest = new ReactorServerHttpRequest(request, bufferFactory);
adaptedResponse = new ReactorServerHttpResponse(response, bufferFactory);
}
catch (URISyntaxException ex) {
logger.error("Invalid URL " + ex.getMessage(), ex);
response.status(HttpResponseStatus.BAD_REQUEST);
return Mono.empty();
}

if (adaptedRequest.getMethod() == HttpMethod.HEAD) {
adaptedResponse = new HttpHeadResponseDecorator(adaptedResponse);
}

return this.httpHandler.handle(adaptedRequest, adaptedResponse)
.doOnError(ex -> logger.error("Handling completed with error", ex))
.doOnSuccess(aVoid -> logger.debug("Handling completed with success"));
}

PS,代码来源于spring-web-5.0.4.RELEASE.jar
此方法为Spring Cloud Gateway的请求入口方法,该方法的作用就是把接收到的HttpServerRequest或者最终需要返回的HttpServerResponse,包装转换为ReactorServerHttpRequest和ReactorServerHttpResponse。

2.2 构造Spring Cloud gateway的上下文ServerWebExchange

在org.springframework.web.server.adapter.HttpWebHandlerAdapter的182行,代码如下所示:

1
2
3
4
5
6
7
@Override
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
ServerWebExchange exchange = createExchange(request, response);
return getDelegate().handle(exchange)
.onErrorResume(ex -> handleFailure(request, response, ex))
.then(Mono.defer(response::setComplete));
}

createExchange()将ServerHttpRequest ServerHttpResponse构建网关上下文ServerWebExchange。


PS:其中org.springframework.web.server.handler.WebHandlerDecorator.getDelegate()通过委托的方式获取一系列需要处理的WebHandler.

2.3 进入Filter链

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle方法,即77行,代码如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
@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);
//TODO: needed or cached?
AnnotationAwareOrderComparator.sort(combined);

logger.debug("Sorted gatewayFilterFactories: "+ combined);
return new DefaultGatewayFilterChain(combined).filter(exchange);
}

2.4 执行Filter链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static class DefaultGatewayFilterChain implements GatewayFilterChain {

private int index;
private final List<GatewayFilter> filters;

public DefaultGatewayFilterChain(List<GatewayFilter> filters) {
this.filters = filters;
}

@Override
public Mono<Void> filter(ServerWebExchange exchange) {
if (this.index < filters.size()) {
GatewayFilter filter = filters.get(this.index++);
return filter.filter(exchange, this);
}
else {
return Mono.empty(); // complete
}
}
}

2.5 Gateway Filter委托为Gloable Filter执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private static class GatewayFilterAdapter implements GatewayFilter {

private final GlobalFilter delegate;

public GatewayFilterAdapter(GlobalFilter delegate) {
this.delegate = delegate;
}

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return this.delegate.filter(exchange, chain);
}

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("GatewayFilterAdapter{");
sb.append("delegate=").append(delegate);
sb.append('}');
return sb.toString();
}
}

2.6 预告待续

在之后的文章中,将会揭秘Spring Cloud Gateway的架构设计,Filter链设计,以及启动装在流程等。

感谢您的阅读,本文由 许进沉思录-专注于互联网与中间件基础架构技术研究 版权所有。如若转载,请注明出处:许进沉思录-专注于互联网与中间件基础架构技术研究(http://xujin.org/sc/gw/gw02/
Spring Cloud Gateway入门案例
Spring Cloud Gateway的After路由断言工厂