Spring-Cloud-Gateway之請求處理流程

Spring-Cloud-Gateway 初始化,路由模型,以及路由加載等源碼在上幾篇學習文檔中已經描述,接下來來看Spring-Cloud-Gateway是怎麼通過這些來對我們的請求進行路由處理的


Spring-Cloud-Gateway整體流程圖

image

  • DispatcherHandler:所有請求的調度器,負載請求分發
  • RoutePredicateHandlerMapping:路由謂語匹配器,用於路由的查找,以及找到路由後返回對應的WebHandler,DispatcherHandler會依次遍歷HandlerMapping集合進行處理
  • FilteringWebHandler : 使用Filter鏈表處理請求的WebHandler,RoutePredicateHandlerMapping找到路由後返回對應的FilteringWebHandler對請求進行處理,FilteringWebHandler負責組裝Filter鏈表並調用鏈表處理請求。

  1. 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());
    }
  1. 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 。

  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的工作原理清晰明瞭的理解。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章