Spring-Cloud-Gateway 初始化,路由模型,以及路由加載等源碼在上幾篇學習文檔中已經描述,接下來來看Spring-Cloud-Gateway是怎麼通過這些來對我們的請求進行路由處理的
Spring-Cloud-Gateway整體流程圖
image
- DispatcherHandler:所有請求的調度器,負載請求分發
- RoutePredicateHandlerMapping:路由謂語匹配器,用於路由的查找,以及找到路由後返回對應的WebHandler,DispatcherHandler會依次遍歷HandlerMapping集合進行處理
- FilteringWebHandler : 使用Filter鏈表處理請求的WebHandler,RoutePredicateHandlerMapping找到路由後返回對應的FilteringWebHandler對請求進行處理,FilteringWebHandler負責組裝Filter鏈表並調用鏈表處理請求。
- DispatcherHandler
org.springframework.web.reactive.DispatcherHandler
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (logger.isDebugEnabled()) {
ServerHttpRequest request = exchange.getRequest();
logger.debug("Processing " + request.getMethodValue() + " request for [" + request.getURI() + "]");
}
//校驗handlerMapping集合是否爲空
if (this.handlerMappings == null) {
return Mono.error(HANDLER_NOT_FOUND_EXCEPTION);
}
//依次遍歷handlerMapping集合進行請求處理
return Flux.fromIterable(this.handlerMappings)
.concatMap(mapping ->
//通過mapping獲取mapping對應的handler
mapping.getHandler(exchange))
.next()
.switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION))
.flatMap(handler ->
//調用handler處理
invokeHandler(exchange, handler))
.flatMap(result -> handleResult(exchange, result));
}
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
if (this.handlerAdapters != null) {
for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
//判斷當前handlerAdapter與handler是否匹配
if (handlerAdapter.supports(handler)) {
return handlerAdapter.handle(exchange, handler);
}
}
}
return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
}
DispatcherHandler的handler執行順序
- 校驗handlerMapping
- 遍歷Mapping獲取mapping對應的handler(此處會找到gateway對應的 RoutePredicateHandlerMapping,並通過 RoutePredicateHandlerMapping獲取handler(FilteringWebHandler))
- 通過handler對應的HandlerAdapter對handler進行調用(gateway使用的 SimpleHandlerAdapter) 即 FilteringWebHandler與SimpleHandlerAdapter對應
org.springframework.web.reactive.result.SimpleHandlerAdapter
public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
WebHandler webHandler = (WebHandler) handler;
//調用handler的handle方法處理請求
Mono<Void> mono = webHandler.handle(exchange);
return mono.then(Mono.empty());
}
- RoutePredicateHandlerMapping
public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
private final FilteringWebHandler webHandler;
private final RouteLocator routeLocator;
public RoutePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator) {
this.webHandler = webHandler;
this.routeLocator = routeLocator;
//設置排序字段1,此處的目的是Spring Cloud Gateway 的 GatewayWebfluxEndpoint 提供 HTTP API ,不需要經過網關
//它通過 RequestMappingHandlerMapping 進行請求匹配處理。RequestMappingHandlerMapping 的 order = 0 ,需要排在 RoutePredicateHandlerMapping 前面。所有,RoutePredicateHandlerMapping 設置 order = 1 。
setOrder(1);
}
@Override
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
//設置mapping到上下文環境
exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName());
//查找路由
return lookupRoute(exchange)
// .log("route-predicate-handler-mapping", Level.FINER) //name this
.flatMap((Function<Route, Mono<?>>) r -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isDebugEnabled()) {
logger.debug("Mapping [" + getExchangeDesc(exchange) + "] to " + r);
}
//將找到的路由信息設置到上下文環境中
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
//返回mapping對應的WebHandler即FilteringWebHandler
return Mono.just(webHandler);
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
//當前未找到路由時返回空,並移除GATEWAY_PREDICATE_ROUTE_ATTR
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isTraceEnabled()) {
logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]");
}
})));
}
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
//通過路由定位器獲取路由信息
return this.routeLocator.getRoutes()
.filter(route -> {
// add the current route we are testing
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, route.getId());
//返回通過謂語過濾的路由信息
return route.getPredicate().test(exchange);
})
// .defaultIfEmpty() put a static Route not found
// or .switchIfEmpty()
// .switchIfEmpty(Mono.<Route>empty().log("noroute"))
.next()
//TODO: error handling
.map(route -> {
if (logger.isDebugEnabled()) {
logger.debug("Route matched: " + route.getId());
}
//校驗路由,目前空實現
validateRoute(route, exchange);
return route;
});
}
}
RoutePredicateHandlerMapping的執行順序
- 通過路由定位器獲取全部路由(RouteLocator)
- 通過路由的謂語(Predicate)過濾掉不可用的路由信息
- 查找到路由信息後將路由信息設置當上下文環境中(GATEWAY_ROUTE_ATTR)
- 返回gatway自定的webhandler(FilteringWebHandler)
備註:
在構建方法中看到setOrder(1);作用:Spring Cloud Gateway 的 GatewayWebfluxEndpoint 提供 HTTP API ,不需要經過網關。
通過 RequestMappingHandlerMapping 進行請求匹配處理。RequestMappingHandlerMapping 的 order = 0 ,需要排在 RoutePredicateHandlerMapping 前面,所以設置 order = 1 。
- FilteringWebHandler
/**
* 通過過濾器處理web請求的處理器
* WebHandler that delegates to a chain of {@link GlobalFilter} instances and
* {@link GatewayFilterFactory} instances then to the target {@link WebHandler}.
*
* @author Rossen Stoyanchev
* @author Spencer Gibb
* @since 0.1
*/
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);
}
/**
* 包裝加載全局的過濾器,將全局過濾器包裝成GatewayFilter
* @param filters
* @return
*/
private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
return filters.stream()
.map(filter -> {
//將所有的全局過濾器包裝成網關過濾器
GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
//判斷全局過濾器是否實現了可排序接口
if (filter instanceof Ordered) {
int order = ((Ordered) filter).getOrder();
//包裝成可排序的網關過濾器
return new OrderedGatewayFilter(gatewayFilter, order);
}
return gatewayFilter;
}).collect(Collectors.toList());
}
@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);
}
}
FilteringWebHandler的執行順序
- 構建一個包含全局過濾器的集合(combined)
- 獲取上下中的路由信息GATEWAY_ROUTE_ATTR
- 將路由裏的過濾器添加到集合中(combined)
- 對過濾器集合進行排序操作
- 通過過濾器集合組裝過濾器鏈表,並進行調用(DefaultGatewayFilterChain與Servlet中的FilterChain與原理是一致的)
- 通過過濾器來處理請求到具體業務服務
整個代碼閱讀下來,使得對Spring-Cloud-Gateway的工作原理清晰明瞭的理解。