spring cloud gateway 的執(zhí)行流程

spring cloud gateway 流程:

spring cloud gateway 官網(wǎng)的流程圖

具體執(zhí)行流程:

  1. DispatcherHandler :接收到請(qǐng)求后匹配 HandlerMapping ,此處會(huì)匹配到 RoutePredicateHandlerMapping ;
  2. RoutePredicateHandlerMapping :匹配 Route ;
  3. FilteringWebHandler :獲取 Route 的 GatewayFilter 列表,創(chuàng)建 GatewayFilterChain 來處理請(qǐng)求。

DispatcherHandler

請(qǐng)求分發(fā)處理器,是WebFlux的訪問入口??催@似曾相識(shí)的樣子,沒錯(cuò),對(duì)應(yīng)到Spring MVC中,跟它承擔(dān)類似作用的,就是DispatcherServlet。DispatcherHander也和DispatcherServlet的請(qǐng)求處理流程類似:


public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    private List<HandlerMapping> handlerMappings;
    private List<HandlerAdapter> handlerAdapters;
    private List<HandlerResultHandler> resultHandlers;

        // 1. 初始化時(shí)從BeanFactory分別拉取類型為:HandlerMapping、HandlerAdapter、HandlerResultHandler
        //    的所有Bean,填充到:handlerMappings、handlerAdapters、resultHandlers
    protected void initStrategies(ApplicationContext context) {
        Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
                context, HandlerMapping.class, true, false);

        ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
                // 對(duì)所有的HandlerMapping排序,實(shí)現(xiàn)按優(yōu)先級(jí)選擇HandlerMapping使用的關(guān)鍵
                // 因?yàn)镠andlerMapping的作用是判斷一個(gè)請(qǐng)求究竟適不適用于它所有對(duì)應(yīng)的Handler
                // 最終是通過Handler去處理一個(gè)請(qǐng)求的,所以假設(shè)我們有一組HandlerMapping
                // 這時(shí)來了個(gè)請(qǐng)求,我們就先把HandlerMapping按getOrder()拿到的優(yōu)先級(jí)排序
                // 然后依次做HandlerMapping.getHandler(request);
                // 如果這個(gè)過程是順序的,或者說同步的,那么第一次有某個(gè)HandlerMapping
                // 拿到了Handler的話,說明它就是我們需要的Mr Right,方法可以直接返回這個(gè)了。
                // 其實(shí)在Spring MVC里 DispatcherServlet就是通過 for if != null return
                // 這樣去順序取HandlerMapping嘗試獲取Handler的。
                // 但是在Spring WebFlux里,Reactor編程將這個(gè)過程異步化了:
                // 通過concatMap()將所有的HandlerMapping異步getHandler(request);
                // 它不保證每個(gè)HandlerMapping執(zhí)行g(shù)etHandler的順序,但保證最終得到的
                // 一組結(jié)果,是按原先HandlerMapping的順序排好的,所以只用next()來獲取
                // 第一個(gè)Handler,就得到了符合HandlerMapping優(yōu)先級(jí)的Handler,得到了
                // 與同步執(zhí)行同樣的結(jié)果。假設(shè)HandlerMapping比較多,或者每個(gè)HandlerMapping
                // 執(zhí)行g(shù)etHandler()的時(shí)間比較久,那么異步是有優(yōu)勢(shì)的,它相當(dāng)于是把這個(gè)過程
                // 并行化了。但也并非一定總有優(yōu)勢(shì),要并行就需要分配多個(gè)線程去做任務(wù),也涉及到
                // 最終結(jié)果的歸并。多個(gè)線程會(huì)占用額外的cpu資源,與其他任務(wù)競(jìng)爭(zhēng)時(shí)間片,CPU調(diào)度
                // 線程造成上下文切換消耗也增加了。并且每個(gè)getHandler的線程計(jì)算結(jié)果是需要維護(hù)
                // 對(duì)應(yīng)的優(yōu)先級(jí)的,因?yàn)樽罱K合并結(jié)果需要保持不改變順序。
        AnnotationAwareOrderComparator.sort(mappings);
        this.handlerMappings = Collections.unmodifiableList(mappings);

        Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
                context, HandlerAdapter.class, true, false);

        this.handlerAdapters = new ArrayList<>(adapterBeans.values());
        AnnotationAwareOrderComparator.sort(this.handlerAdapters);

        Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
                context, HandlerResultHandler.class, true, false);

        this.resultHandlers = new ArrayList<>(beans.values());
        AnnotationAwareOrderComparator.sort(this.resultHandlers);
    }

        // 2.遍歷handlerMappings,獲取對(duì)應(yīng)的WebHandler
    @Override
    public Mono<Void> handle(ServerWebExchange exchange) {
        if (this.handlerMappings == null) {
            return createNotFoundError();
        }
        return Flux.fromIterable(this.handlerMappings)
                                // a.此處會(huì)匹配到RoutePredicateHandlerMapping
                                // b.RoutePredicateHandlerMapping匹配請(qǐng)求對(duì)應(yīng)的 Route
                                // c.返回FilteringWebHandler
                .concatMap(mapping -> mapping.getHandler(exchange))
                .next()
                .switchIfEmpty(createNotFoundError())
                                // d.執(zhí)行Handler
                .flatMap(handler -> invokeHandler(exchange, handler))
                                // e.處理result
                .flatMap(result -> handleResult(exchange, result));
    }

        // 3.執(zhí)行Handler,得到HandlerResult
    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));
    }

        // 5.處理返回結(jié)果
    private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
        return getResultHandler(result).handleResult(exchange, result)
                .checkpoint("Handler " + result.getHandler() + " [DispatcherHandler]")
                .onErrorResume(ex ->
                        result.applyExceptionHandler(ex).flatMap(exResult -> {
                            String text = "Exception handler " + exResult.getHandler() +
                                    ", error=\"" + ex.getMessage() + "\" [DispatcherHandler]";
                            return getResultHandler(exResult).handleResult(exchange, exResult).checkpoint(text);
                        }));
    }

        // 4.根據(jù)Result類型,獲取處理返回結(jié)果的Handler
    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的流程簡(jiǎn)單點(diǎn)說:先初始換那些handlerMapping、handlerAdater、resultAdater,從中遍歷了handlerMapping,最終它找到RoutePredicateHandlerMapping,就是開始第二步驟。

RoutePredicateHandlerMapping

  • 通過路由定位器獲取全部路由(RouteLocator)
  • 通過路由的謂語(Predicate)過濾掉不可用的路由信息
  • 查找到路由信息后將路由信息設(shè)置當(dāng)上下文環(huán)境中(GATEWAY_ROUTE_ATTR)
  • 返回gatway自定的webhandler(FilteringWebHandler)

執(zhí)行他的核心方法:

@Override
    protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
        // don't handle requests on management port if set and different than server port
        if (this.managementPortType == DIFFERENT && this.managementPort != null
                && exchange.getRequest().getURI().getPort() == this.managementPort) {
            return Mono.empty();
        }
        exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, 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);
                    return Mono.just(webHandler);
                }).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
                    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()
                // individually filter routes so that filterWhen error delaying is not a
                // problem
                .concatMap(route -> Mono.just(route).filterWhen(r -> {
                    // add the current route we are testing
                    exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
                    return r.getPredicate().apply(exchange);
                })
                        // instead of immediately stopping main flux due to error, log and
                        // swallow it
                        .doOnError(e -> logger.error(
                                "Error applying predicate for route: " + route.getId(),
                                e))
                        .onErrorResume(e -> Mono.empty()))
                // .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;
                });

        /*
         * TODO: trace logging if (logger.isTraceEnabled()) {
         * logger.trace("RouteDefinition did not match: " + routeDefinition.getId()); }
         */
    }
看lookupRoute方法就知道去找相應(yīng)的Route了,是根據(jù)routeId去找的。找到相應(yīng)的route,再返回FilteringWebHandler。

FilteringWebHandler 過濾web請(qǐng)求處理

她的本職工作是將GlobalFilter(全局過濾器)、GatewayFilter(一般來說是我們自己配置的,當(dāng)然也默認(rèn)內(nèi)置了一些,也內(nèi)含了自己在application配置文件中配的defaultFilter[如果有陪置的話]),放到同一個(gè)List里進(jìn)行優(yōu)先級(jí)排序,生成一個(gè)過濾器鏈。執(zhí)行過濾器鏈,就能順序執(zhí)行鏈中保存的所有Filter。

public class FilteringWebHandler implements WebHandler {
    // 所有全局過濾器
    private final List<GatewayFilter> globalFilters;

    public FilteringWebHandler(List<GlobalFilter> globalFilters) {
        // 1.初始化時(shí)加載所有全局過濾器,將他們適配為GatewayFilter類型,方便等會(huì)做合并
        this.globalFilters = loadFilters(globalFilters);
    }
    // 適配器模式,通過兩次套娃把GlobalFilter封裝成GatewayFilter類型
    private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
    return filters.stream().map(filter -> {
            // 2.Adapter持有GlobalFilter的引用
        GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
        if (filter instanceof Ordered) {
        int order = ((Ordered) filter).getOrder();
                // 3.OrderedGatewayFilter再持有一個(gè)Adapter
                // 其實(shí)這里搞的挺無語的,那我直接返回Adapter又不是不能用,畢竟接口相同
                // 說白了,還是跟職責(zé)隔離、設(shè)計(jì)解耦有關(guān)
                // 就好比有時(shí)我們會(huì)糾結(jié)干嘛不直接把路由配置讀成Route是類似的
                // 因?yàn)槲覀兊乃季S模式,就是快點(diǎn)達(dá)到目的,而忽略了擴(kuò)展性
                // 假設(shè)現(xiàn)在我們需要有一個(gè)服務(wù)提供多個(gè)接口,包括了Filter接口的功能
                // 那么,我們還是直接在Adapter上加接口,再持有一個(gè)跟它功能無關(guān)的工具人干活?
                // 那職責(zé)就完全亂套了,我們大可以這樣:
                // Kunkun implements ISing,IJump,IRap,IBasketball {
                //     private ISing singAdapter;
                //     private IJump jumpAdapter;
                //     private IRap rapAdapter;
                //     private IBasketball basketballAdapter;
                // }
                // 那么坤坤就會(huì)唱、跳、rap、籃球了
        return new OrderedGatewayFilter(gatewayFilter, order);
        }
        return gatewayFilter;
        }).collect(Collectors.toList());
}

public Mono<Void> handle(ServerWebExchange exchange) {
    // 1.從exchange里拿到第二步匹配好的Route(匹配到后塞進(jìn)去的)
    Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
    // 2.通過這個(gè)Route拿到它對(duì)應(yīng)的GatewayFilter列表
    List<GatewayFilter> gatewayFilters = route.getFilters();
    // 3.把前面已經(jīng)適配為GatewayFilter的全局過濾器拿過來,初始化一個(gè)總的過濾器列表
    List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
    // 4.然后把從Route里拿到的過濾器列表也塞進(jìn)去合并
    combined.addAll(gatewayFilters);
    // 5.對(duì)總的過濾器列表按優(yōu)先級(jí)排序
    AnnotationAwareOrderComparator.sort(combined);
    // 6.通過這個(gè)總的過濾器列表構(gòu)造一個(gè)過濾器鏈來執(zhí)行過濾邏輯
    return new DefaultGatewayFilterChain(combined).filter(exchange);
}
所以總結(jié)就是將globalFilter和route的filters結(jié)合在一塊,形成一個(gè)過濾器鏈,之后請(qǐng)求就去逐個(gè)執(zhí)行過濾器鏈的過濾器。

參考文章:

spring cloud gateway 專題收錄1

spring cloud gateway 專題收錄2

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容