Spring WebFlux架構
Spring Cloud Gateway是在Spring WebFlux基礎上構造的新一代網關係統。Spring WebFlux和Spring MVC架構和API上幾乎完全一致,只不過Spring WebFlux底層使用的是響應式接口,Spring MVC是構建在Servlet之上的阻塞式編程架構。這裏的阻塞式和非阻塞式不僅是我們常說的Web服務器I/O,Spring WebFlux構建在Reactor模型之上,Reactor是一種全域的響應式編程模型。
以上是Spring WebFlux和Spring MVC架構的官方對比圖,兩者都採用前端調度器模式(Dispatcher)實現,其他像關鍵部件也十分相似。關於兩者的選型官方也給出了權威的說明:Web on Reactive Stack
Spring Cloud Gateway架構
Spring Cloud Gateway是構建在Spring WebFlux之上,Spring WebFlux已經提供了網絡服務能力,而且提供了很好的封裝。所以Spring Cloud Gateway只需要實現Spring WebFlux擴展所需的組件,並且封裝自身所需的功能就可以了。Spring Cloud Gateway的整體架構如下所示:
藉助Spring WebFlux的網絡服務能力,Spring Cloud Gateway僅需實現自定義的HandlerMapping、WebHandler兩個關鍵組件即可完成Spring WebFlux的擴展。除此之外,Spring Cloud Gateway只需要關注自身需要的路由功能,以及其他API網關通用能力。
RouteLocator負責路由的初始化和路由的選擇,HandlerMapping在處理請求時調用RouteLocator獲取處理此次請求的Route,處理過程是逐個調用所有Route的Predicates判斷本次請求是否由自己處理。
WebHandler取出HandlerMapping階段匹配的Route所有的Filters,拼裝上全局Filters,構建過濾器鏈。濾器鏈中的過濾器完成請求處理、解析、重寫、負載均衡等操作,最後執行過濾器ProxyFilter完成請求的轉發。
HandlerMapping分析
HandlerMapping的實現類是RoutePredicateHandlerMapping
,其中關鍵方式是protected Mono<?> getHandlerInternal(ServerWebExchange exchange)
,其主要功能是lookupRoute
。
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
//獲取所有路由
return this.routeLocator.getRoutes()
//過濾可用路由
.concatMap(route -> Mono.just(route).filterWhen(r -> {
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
return r.getPredicate().apply(exchange);
})
.doOnError(e -> logger.error(
"Error applying predicate for route: " + route.getId(),
e))
.onErrorResume(e -> Mono.empty()))
//只取出命中的所有Route中的第一個
.next()
//驗證路由可用,validateRoute是一個空方法,默認是不做處理
.map(route -> {
if (logger.isDebugEnabled()) {
logger.debug("Route matched: " + route.getId());
}
validateRoute(route, exchange);
return route;
});
}
WebHandler分析
Spring Cloud Gateway的WebHandler實現是FilteringWebHandler
,其中關鍵方式是handle
。
public Mono<Void> handle(ServerWebExchange exchange) {
//取出RoutePredicateHandlerMapping命中的Route
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
List<GatewayFilter> gatewayFilters = route.getFilters();
//拼接全局Filters和Route自己的Filters,並且按照Ordered值排序
List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
combined.addAll(gatewayFilters);
AnnotationAwareOrderComparator.sort(combined);
if (logger.isDebugEnabled()) {
logger.debug("Sorted gatewayFilterFactories: " + combined);
}
//組裝過濾器鏈,並且觸發鏈式過濾
return new DefaultGatewayFilterChain(combined).filter(exchange);
}