1、Spring Cloud Gateway 源碼解析概述
API網關作為后端服務的統一入口,可提供請求路由、協議轉換、安全認證、服務鑒權、流量控制、日志監控等服務。那么當請求到達網關時,網關都做了哪些處理以及怎么處理的呢?我們帶着這些問題,順着網關的處理流程,一步步進行源碼閱讀,一探究竟。
2、Spring Cloud Gateway 網關處理流程概述

1、請求發送到網關, DispatcherHandler 是HTTP請求的中央分發器,將請求匹配到響應的HandlerMapping;
2、請求與處理器之間有一個映射關系,網關將會對請求進行路由,handler會匹配到RoutePredicateHandlerMapping,以匹配到對應的Route
3、接着請求到達網關的web處理器,該WebHandler 代理了一系列網關過濾器和全局過濾器的實例,此時會對請求頭或響應頭進行處理
4、最后轉發到具體的代理服務
3、Spring Cloud Gateway 初始化
當啟動網關服務時,引入的Spring Cloud Gateway 的starter將會自動加載一些配置:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
# WebFlux 依賴檢查配置類
org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration,\
# 網關核心自動配置類,配置路由規則、過濾器等
org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\
# 客戶端負載均衡自動配置類
org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration,\
# 網關指標自動配置類
org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,\
# redis 自動配置類
org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,\
# 服務發現客戶端自動配置類
org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration
下面不會一一列出以上的配置,這里主要看一下設計網關屬性的配置。GatewayProperties是網關配置中的核心配置屬性類:
@ConfigurationProperties("spring.cloud.gateway")
@Validated
public class GatewayProperties {
//路由列表
@NotNull
@Valid
private List<RouteDefinition> routes = new ArrayList();
//默認過濾器
private List<FilterDefinition> defaultFilters = new ArrayList();
//流媒體類型
private List<MediaType> streamingMediaTypes;
public GatewayProperties() {
this.streamingMediaTypes = Arrays.asList(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_STREAM_JSON);
}
public List<RouteDefinition> getRoutes() {
return this.routes;
}
public void setRoutes(List<RouteDefinition> routes) {
this.routes = routes;
}
public List<FilterDefinition> getDefaultFilters() {
return this.defaultFilters;
}
public void setDefaultFilters(List<FilterDefinition> defaultFilters) {
this.defaultFilters = defaultFilters;
}
public List<MediaType> getStreamingMediaTypes() {
return this.streamingMediaTypes;
}
public void setStreamingMediaTypes(List<MediaType> streamingMediaTypes) {
this.streamingMediaTypes = streamingMediaTypes;
}
public String toString() {
return "GatewayProperties{routes=" + this.routes + ", defaultFilters=" + this.defaultFilters + ", streamingMediaTypes=" + this.streamingMediaTypes + '}';
}
}
GatewayProperties 有三個屬性,分別是路由列表(對應路由定義對象RouteDefinition)、默認過濾器列表(對應過濾器對象FilterDefinition)、流媒體類型列表(對應流媒體對象MediaType)
4、網關處理器
當請求到達網關時,會有各種web處理器對請求進行匹配和處理,下面我們將會對主要的幾個web處理器進行講解

graph LR
DispatcherHandler -->RoutePredicateHandlerMapping
RoutePredicateHandlerMapping-->FilteringWebHandler
FilteringWebHandler-->DefaultGatewayFilterChain
4.1、請求分發器 DispatcherHandler
Spring Cloud Gateway 引入了Spring WebFlux, DispatcherHandler 是 請求分發處理器,是網關請求的入口。之前的項目中引入的是 Spring MVC,它的分發 處理器是 DispatcherServlet。下面看一下網關收到請求后是如何處理的:
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
private static final Exception HANDLER_NOT_FOUND_EXCEPTION;
private static final Log logger;
@Nullable
private List<HandlerMapping> handlerMappings;
@Nullable
private List<HandlerAdapter> handlerAdapters;
@Nullable
private List<HandlerResultHandler> resultHandlers;
public DispatcherHandler() {
}
public DispatcherHandler(ApplicationContext applicationContext) {
this.initStrategies(applicationContext);
}
@Nullable
public final List<HandlerMapping> getHandlerMappings() {
return this.handlerMappings;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.initStrategies(applicationContext);
}
//根據請求匹配對應的出列器
public Mono<Void> handle(ServerWebExchange exchange) {
if (logger.isDebugEnabled()) {
ServerHttpRequest request = exchange.getRequest();
logger.debug("Processing " + request.getMethodValue() + " request for [" + request.getURI() + "]");
}
return this.handlerMappings == null ? Mono.error(HANDLER_NOT_FOUND_EXCEPTION) : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> {
return mapping.getHandler(exchange);
}).next().switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION)).flatMap((handler) -> {
return this.invokeHandler(exchange, handler);
}).flatMap((result) -> {
return this.handleResult(exchange, result);
});
}
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
if (this.handlerAdapters != null) {
for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
if (handlerAdapter.supports(handler)) {
return handlerAdapter.handle(exchange, handler);
}
}
}
return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
}
private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
return getResultHandler(result).handleResult(exchange, result)
.onErrorResume(ex -> result.applyExceptionHandler(ex).flatMap(exceptionResult ->
getResultHandler(exceptionResult).handleResult(exchange, exceptionResult)));
}
private HandlerResultHandler getResultHandler(HandlerResult handlerResult) {
if (this.resultHandlers != null) {
for (HandlerResultHandler resultHandler : this.resultHandlers) {
if (resultHandler.supports(handlerResult)) {
return resultHandler;
}
}
}
throw new IllegalStateException("No HandlerResultHandler for " + handlerResult.getReturnValue());
}
}
DispatcherHandler 實現了 WebHandler 接口,WebHandler 接口是用來處理 Web請求的。在DispatcherHandler 的構造函數中會初始化 HandlerMapping,核心 處理 的方法是 handle( ServerWebExchange exchange), 而 HandlerMapping 是一個定義 了請求與處理器對象映射的接口且有多個實現類,如 ControllerEndpointHandlerMapping 和 RouterFunctionMapping。
invokeHandler 方法調用相應的 WebHandler,獲取該WebHandler對應的適配器。
4.2、路由斷言處理器 RoutePredicateHandlerMapping
RoutePredicateHandlerMapping 用於匹配具體的Route,並返回處理 Route 的 FilteringWebHandler
public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
private final FilteringWebHandler webHandler;
private final RouteLocator routeLocator;
public RoutePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties) {
this.webHandler = webHandler;
this.routeLocator = routeLocator;
this.setOrder(1);
this.setCorsConfigurations(globalCorsProperties.getCorsConfigurations());
}
................................
}
RoutePredicateHandlerMapping 的構造函數接受兩個參數,
FilteringWebHandler 網關過濾器 和 RouteLocator 路由定位器, setOrder( 1) 用於設置該對象初始化的優先級。
Spring Cloud Gateway 的 GatewayWebfluxEndpoint 提供的 HTTP API 不需要經過 網關轉發,它通過 RequestMappingHandlerMapping 進行請求匹配處理,因此需要將 RoutePredicateHandlerMapping 的優先級設置為 低於RequestMappingHandlerMapping。
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
//設置網關處理器為 RoutePredicateHandlerMapping
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_HANDLER_MAPPER_ATTR, this.getClass().getSimpleName());
return this.lookupRoute(exchange).flatMap((r) -> {
exchange.getAttributes().remove(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Mapping [" + this.getExchangeDesc(exchange) + "] to " + r);
}
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR, r);
return Mono.just(this.webHandler);
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
exchange.getAttributes().remove(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR);
if (this.logger.isTraceEnabled()) {
this.logger.trace("No RouteDefinition found for [" + this.getExchangeDesc(exchange) + "]");
}
})));
}
//路由順序匹配
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
return this.routeLocator.getRoutes().concatMap((route) -> {
return Mono.just(route).filterWhen((r) -> {
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
return (Publisher)r.getPredicate().apply(exchange);
}).doOnError((e) -> {
this.logger.error("Error applying predicate for route: " + route.getId(), e);
}).onErrorResume((e) -> {
return Mono.empty();
});
}).next().map((route) -> {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Route matched: " + route.getId());
}
//校驗路由有效性
this.validateRoute(route, exchange);
return route;
});
}
以上為獲取 handler 的方法,匹配請求的Route,並返回處理 Route的過濾器 FilteringWebHandler。
首先設置GATEWAY_ HANDLER_ MAPPER_ ATTR 為 RoutePredicateHandlerMapping 的類名
然后順序匹配對應的 Route,RouteLocator 接口獲取網關中定義的路由,並根據請求信息與路由定義的斷言按照優先級匹配。
最后找到匹配的Route,並返回響應的處理器。
4.3、過濾器處理器 FilteringWebHandler
FilteringWebHandler 通過創建所請求 Route 對應的 GatewayFilterChain, 在網關進行過濾處理
public class FilteringWebHandler implements WebHandler {
protected static final Log logger = LogFactory.getLog(FilteringWebHandler.class);
private final List<GatewayFilter> globalFilters;
public FilteringWebHandler(List<GlobalFilter> globalFilters) {
this.globalFilters = loadFilters(globalFilters);
}
private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
return (List)filters.stream().map((filter) -> {
//適配 GatewayFilter
FilteringWebHandler.GatewayFilterAdapter gatewayFilter = new FilteringWebHandler.GatewayFilterAdapter(filter);
//是否實現了 Ordered,如果實現了,則返回OrderedGatewayFilter
if (filter instanceof Ordered) {
int order = ((Ordered)filter).getOrder();
return new OrderedGatewayFilter(gatewayFilter, order);
} else {
return gatewayFilter;
}
}).collect(Collectors.toList());
}
public Mono<Void> handle(ServerWebExchange exchange) {
Route route = (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
List<GatewayFilter> gatewayFilters = route.getFilters();
List<GatewayFilter> combined = new ArrayList(this.globalFilters);
//加入全局過濾器
combined.addAll(gatewayFilters);
//過濾器排序
AnnotationAwareOrderComparator.sort(combined);
logger.debug("Sorted gatewayFilterFactories: " + combined);
//按照優先級對請求進行過濾
return (new FilteringWebHandler.DefaultGatewayFilterChain(combined)).filter(exchange);
}
}
全局變量 globalFilters 是Spring Cloud Gateway 定義的全局過濾器,構造函數通過傳入全局過濾器,對過濾器進行適配。因為過濾器有優先級,loadFilters 該方法主要是判斷過濾器是否實現了 Ordered 接口,如果實現了則返回OrderedGatewayFilter,否則返回適配的過濾器。最后將適配的過濾器加入全局過濾器,並對過濾器進行排序,根據優先級對請求進行處理。
4.4、生成過濾器鏈
FilteringWebHandler 內部靜態類 DefaultGatewayFilterChain
private static class DefaultGatewayFilterChain implements GatewayFilterChain {
private final int index;
private final List<GatewayFilter> filters;
public DefaultGatewayFilterChain(List<GatewayFilter> filters) {
this.filters = filters;
this.index = 0;
}
private DefaultGatewayFilterChain(FilteringWebHandler.DefaultGatewayFilterChain parent, int index) {
this.filters = parent.getFilters();
this.index = index;
}
public List<GatewayFilter> getFilters() {
return this.filters;
}
public Mono<Void> filter(ServerWebExchange exchange) {
return Mono.defer(() -> {
if (this.index < this.filters.size()) {
GatewayFilter filter = (GatewayFilter)this.filters.get(this.index);
FilteringWebHandler.DefaultGatewayFilterChain chain = new FilteringWebHandler.DefaultGatewayFilterChain(this, this.index + 1);
return filter.filter(exchange, chain);
} else {
return Mono.empty();
}
});
}
}
FilteringWebHandler 的 handle 方法,首先獲取請求對應的路由過濾器和全局過濾器,並將兩者合並。
然后對過濾器進行排序。
最后按照優先級生成過濾器鏈,對請求進行過濾處理。
過濾器鏈的生成是通過內部靜態類 DefaultGatewayFilterChain 實現的,該類實現了GatewayFilterChain 接口,最后對請求按照過濾器優先級進行過濾。
