【Spring Cloud Gateway專題】二、核心組件初始化步驟及請求流程

1、前言

在當下學習和使用 spring cloud 技術棧的熱潮中,網關已經成了不可或缺的內容。開發者在選擇用來解決特定領域內問題的框架時,多瞭解幾款相關同類產品可加大選擇餘地。除了 Netflix 的 zuul 之外,spring cloud gateway 可作爲開發者的另一個選擇。
Zuul 分 1.x 和 2.x 版本。Zuul 2.x 版本和 spring cloud gateway 都使用 Non-Blocking I/O 模型。
——節選自“https://mp.weixin.qq.com/s/jCQR1WkOsiOzozMAeIPk3g 「歐文雪」”
文章多參考
「歐文雪」:https://mp.weixin.qq.com/s/jCQR1WkOsiOzozMAeIPk3g
芋道源碼http://www.iocoder.cn/categories/Spring-Cloud-Gateway/

1.1 Gateway 技術棧

開發者瞭解以下技術,學習 gateway 會更加容易。
① project reactor,遵循 Reactive Streams Specification,使用非阻塞編程模型。
② webflux,基於 spring 5.x 和 reactor-netty 構建,不依賴於 Servlet 容器,但是可以在支持 Servlet 3.1 Non-Blocking IO API 的容器上運行。

1.2 Gateway 工作機制

Spring cloud gateway 的工作機制大體如下:
① Gateway 接收客戶端請求。
② 客戶端請求與路由信息進行匹配,匹配成功的才能夠被髮往相應的下游服務。
③ 請求經過 Filter 過濾器鏈,執行 pre 處理邏輯,如修改請求頭信息等。
④ 請求被轉發至下游服務並返回響應。
⑤ 響應經過 Filter 過濾器鏈,執行 post 處理邏輯。
⑥ 向客戶端響應應答。
Gateway 工作機制可參考下圖(圖片來自官方文檔):
在這裏插入圖片描述
本文主要介紹 spring cloud gateway 核心組件的初始化步驟。然後,描述當一個外部請求獲取後,經過的處理流程。

2、核心組件

2.1 最核心組件 Route

(1) Route

Route 是 gateway 中最基本的組件之一,表示一個具體的路由信息載體。
Route源代碼:

public class Route implements Ordered {

    private final String id; // ①

    private final URI uri; // ②

    private final int order; // ③

    private final AsyncPredicate<ServerWebExchange> predicate; // ④

    private final List<GatewayFilter> gatewayFilters; // ⑤

Route 主要定義瞭如下幾個部分:

① id,標識符,區別於其他 Route。

② destination uri,路由指向的目的地 uri,即客戶端請求最終被轉發的目的地。

③ order,用於多個 Route 之間的排序,數值越小排序越靠前,匹配優先級越高。

④ predicate,謂語,表示匹配該 Route 的前置條件,即滿足相應的條件纔會被路由到目的地 uri。

⑤ gateway filters,過濾器用於處理切面邏輯,如路由轉發前修改請求頭等。

(2) AsyncPredicate

Predicate 即 Route 中所定義的部分,用於條件匹配,請參考 Java 8 提供的 Predicate 和 Function。
AsyncPredicate源代碼:

public interface AsyncPredicate<T> extends Function<T, Publisher<Boolean>> {

    default AsyncPredicate<T> and(AsyncPredicate<? super T> other) { // ①
        Objects.requireNonNull(other, "other must not be null");
        return t -> Flux.zip(apply(t), other.apply(t))
                .map(tuple -> tuple.getT1() && tuple.getT2());
    }

    default AsyncPredicate<T> negate() { // ②
        return t -> Mono.from(apply(t)).map(b -> !b);
    }

    default AsyncPredicate<T> or(AsyncPredicate<? super T> other) { // ③
        Objects.requireNonNull(other, "other must not be null");
        return t -> Flux.zip(apply(t), other.apply(t))
                .map(tuple -> tuple.getT1() || tuple.getT2());
    }
}

AsyncPredicate 定義了 3 種邏輯操作方法:

① and ,與操作,即兩個 Predicate 組成一個,需要同時滿足。

② negate,取反操作,即對 Predicate 匹配結果取反。

③ or,或操作,即兩個 Predicate 組成一個,只需滿足其一。

(3) GatewayFilter

很多框架都有 Filter 的設計,用於實現可擴展的切面邏輯。
GatewayFilter 源代碼:

public interface GatewayFilter extends ShortcutConfigurable {

    String NAME_KEY = "name";
    String VALUE_KEY = "value";

    /**
     * Process the Web request and (optionally) delegate to the next
     * {@code WebFilter} through the given {@link GatewayFilterChain}.
     * @param exchange the current server exchange
     * @param chain provides a way to delegate to the next filter
     * @return {@code Mono<Void>} to indicate when request processing is complete
     */
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

Filter 最終是通過 filter chain 來形成鏈式調用的,每個 filter 處理完 pre filter 邏輯後委派給 filter chain,filter chain 再委派給下一下 filter。

GatewayFilterChain 源代碼:

public interface GatewayFilterChain {

    /**
     * Delegate to the next {@code WebFilter} in the chain.
     * @param exchange the current server exchange
     * @return {@code Mono<Void>} to indicate when request handling is complete
     */
    Mono<Void> filter(ServerWebExchange exchange);

}

2.2 如何構建 Route

如何構建 Route 組件?Spring 提供了兩種方式:外部化配置和編程的方式。

(1) 外部化配置

Spring cloud gateway 提供了一些開箱即用的 Predicate 和 Filter,它們通過工廠模式來生產。
下面這個例子由官方文檔中的兩個示例組合而成。

spring:
  cloud:
    gateway: # ①
      routes: # ②
      - id: cookie_route # ③
        uri: http://example.org # ④
        predicates: # ⑤
        - Cookie=chocolate, ch.p # ⑥
        filters: # ⑦
        - AddRequestHeader=X-Request-Foo, Bar # ⑧

詳細說明:

① “spring.cloud.gateway” 爲固定前綴。

② 定義路由信息列表,即可定義多個路由。

③ 聲明瞭一個 id 爲 “cookie_route” 的路由。

④ 定義了路由的目的地 uri,即請求轉發的目的地。

⑤ 聲明 predicates,即請求滿足相應的條件才能匹配成功。

⑥ 定義了一個 Predicate,當名稱爲 chocolate 的 Cookie 的值匹配ch.p時 Predicate 才能夠匹配,它由 CookieRoutePredicateFactory 來生產。

⑦ 聲明 filters,即路由轉發前後處理的過濾器。

⑧ 定義了一個 Filter,所有的請求轉發至下游服務時會添加請求頭 X-Request-Foo:Bar ,由AddRequestHeaderGatewayFilterFactory 來生產。

(2) 編程方式

開發者還可以通過編程的方式來定義 Route,編程的方式會更加靈活。
下面通過 fluent API RouteLocatorBuilder 來構建 RouteLocator。
示例(根據官方文檔改造):

// static imports from GatewayFilters and RoutePredicates
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { // ①
    return builder.routes() // ②
            .route(r -> r.host("**.abc.org").and().path("/image/png") // ③
                .filters(f ->
                        f.addResponseHeader("X-TestHeader", "foobar")) // ④
                .uri("http://httpbin.org:80") // ⑤
            )
            .build();
}

① RouteLocatorBuilder bean 在 spring-cloud-starter-gateway 模塊自動裝配類中已經聲明,可直接使用。RouteLocator 封裝了對 Route 獲取的定義,可簡單理解成工廠模式。

② RouteLocatorBuilder 可以構建多個路由信息。

③ 指定了 Predicates,這裏包含兩個:
請求頭Host需要匹配**.abc.org,通過 HostRoutePredicateFactory 產生。
請求路徑需要匹配/image/png,通過 PathRoutePredicateFactory 產生。

④ 指定了一個 Filter,下游服務響應後添加響應頭X-TestHeader:foobar,通過AddResponseHeaderGatewayFilterFactory 產生。

⑤ 指定路由轉發的目的地 uri。

如果說外部化配置完全是個黑盒,那麼通過編程的方式使開發者向白盒靠近了一步。因爲開發者需要使用 gateway 的 api,需要開發者對其有工作機制有所瞭解。

2.3 Route 構建的原理

產生Route的兩種方式包括外部化配置方式和自定義編程方式,下圖展示了這兩種方式。
在這裏插入圖片描述
通過自定義RouteLocator方式構建,直接由開發者通過工廠方法RouteLocatorBuilder產生一個Route。故不再細解。本節重點講通過外部化配置方式構建。

(1) 通過RouteDefinition構建

外部化配置方式由RouteDefinitionLocator產生RouteDefinition,再由RouteDefinitionRouteLocator將RouteDefinition轉換爲Route。其中,外部化配置方式除了上文中提到的配置文件方式(PropertiesRouteDefinitionLocator)外,還包括RouteDefinitionRepository、DiscoveryClientRouteDefinitionLocator(通過註冊中心發現)。
關於RouteDefinitionRouteLocator如何將RouteDefinition轉換爲Route,請參考芋道源碼route-locator-route-definition

(2) RouteDefinition

這裏需要先介紹RouteDefinition類,RouteDefinition類定義了外部化配置參數的類,它會被轉化爲Route。RouteDefinition 源碼如下:

public class RouteDefinition {
    @NotEmpty
    private String id = UUID.randomUUID().toString(); // ①

    @NotEmpty
    @Valid
    private List<PredicateDefinition> predicates = new ArrayList<>();  // ②

    @Valid
    private List<FilterDefinition> filters = new ArrayList<>();  // ③

    @NotNull
    private URI uri;  // ④

    private int order = 0; // ⑤
}

① 定義 Route 的 id,默認使用 UUID。

② 定義 Predicate。

③ 定義 Filter。

④ 定義目的地 URI。

⑤ 定義 Route 的序號。

可見,RouteDefinition 中所定義的屬性與 Route 本身是一一對應的。

(3) FilterDefinition

同樣遵循組件名前綴 + Definition 後綴的命名規範,用於定義 Filter。

public class FilterDefinition {
    @NotNull
    private String name; // ①
    private Map<String, String> args = new LinkedHashMap<>(); // ②

① 定義了 Filter 的名稱,符合特定的命名規範,爲對應的工廠名前綴。

② 一個鍵值對參數用於構造 Filter 對象。

外部配置到 FilterDefinition 對象綁定
以 AddRequestHeader GatewayFilter Factory 爲例:

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: http://example.org
        filters:
        - AddRequestHeader=X-Request-Foo, Bar # ①

① 這一行配置被 spring 解析後會綁定到一個 FilterDefinition 對象。

AddRequestHeader ,對應 FilterDefinition 中的 name 屬性。
X-Request-Foo, Bar ,會被解析成 FilterDefinition 中的 Map 類型屬性 args。此處會被解析成兩組鍵值對,以英文逗號將=後面的字符串分隔成數組,key是固定字符串 genkey + 數組元素下標,value爲數組元素自身。
相關源碼:

// FilterDefinition 構造函數
public FilterDefinition(String text) {
    int eqIdx = text.indexOf("=");
    if (eqIdx <= 0) {
        setName(text);
        return;
    }
    setName(text.substring(0, eqIdx));
    String[] args = tokenizeToStringArray(text.substring(eqIdx+1), ",");
    for (int i=0; i < args.length; i++) {
        this.args.put(NameUtils.generateName(i), args[i]); // ①
    }
}

// ① 使用到的工具類 NameUtils 源碼

public class NameUtils {
    public static final String GENERATED_NAME_PREFIX = "_genkey_";
    public static String generateName(int i) {
        return GENERATED_NAME_PREFIX + i;
    }
}

(4) PredicateDefinition

同樣遵循組件名前綴 + Definition 後綴的命名規範,用於定義 Predicate。

public class PredicateDefinition {
    @NotNull
    private String name; // ①
    private Map<String, String> args = new LinkedHashMap<>(); // ②

① 定義了 Predicate 的名稱,它們要符固定的命名規範,爲對應的工廠名稱。

② 一個 Map 類型的參數,構造 Predicate 使用到的鍵值對參數。
外部化配置綁定到 PredicateDefinition 源碼邏輯與 FilterDefinition 類似,不再贅述。

2.4 框架初始化步驟

Spring boot 遵循規約大於配置的原則,starter 模塊都有對應的以模塊名稱作前綴,以 “AutoConfiguration” 後綴的自動裝配類。同樣的還有以模塊名前綴,以Properties後綴的配置類作爲支持。Gateway 模塊自動裝配類及對應的配置類參考:
在這裏插入圖片描述
在官方提供的實例項目 spring-cloud-gateway-sample ,我們看到 GatewaySampleApplication 上有 @EnableAutoConfiguration 註解。因爲該項目導入了 spring-cloud-gateway-core 依賴庫,它會掃描 Spring Cloud Gateway 的配置。(注意,我們的應用中,可能使用了@SpringBootApplication註解,該註解包含@EnableAutoConfiguration註解)
網關初始化步驟參考:芋道源碼 網關初始化

3、請求流程

3.1 網關請求步驟

我們一起來看看,一個請求是怎麼被 Spring Cloud Gateway 處理的,如下圖 :
在這裏插入圖片描述
轉換爲官方的圖:
在這裏插入圖片描述
org.springframework.web.reactive.DispatcherHandler :接收到請求,匹配 HandlerMapping ,此處會匹配到 RoutePredicateHandlerMapping 。
org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping :接收到請求,匹配 Route 。
org.springframework.cloud.gateway.handler.FilteringWebHandler :獲得 Route 的 GatewayFilter 數組,創建 GatewayFilterChain 處理請求。

3.2 DispatcherHandler

org.springframework.web.reactive.DispatcherHandler ,請求分發處理器,Spring WebFlux 的訪問入口。可能大多數人對這個類都比較陌生,我們來看看他在 Spring MVC 的兄弟 DispatcherServlet 是不是就有點熟悉的感覺。

下面來看看 DispatcherHandler#handle(ServerWebExchange) 方法,代碼如下 :

1: public class DispatcherHandler implements WebHandler, ApplicationContextAware {
 2: 
 3: 	@Nullable
 4: 	private List<HandlerMapping> handlerMappings;
 5: 
 6: 	@Nullable
 7: 	private List<HandlerAdapter> handlerAdapters;
 8: 
 9: 	@Override
10: 	public Mono<Void> handle(ServerWebExchange exchange) {
11: 		if (logger.isDebugEnabled()) {
12: 			ServerHttpRequest request = exchange.getRequest();
13: 			logger.debug("Processing " + request.getMethodValue() + " request for [" + request.getURI() + "]");
14: 		}
15: 		if (this.handlerMappings == null) {
16: 			return Mono.error(HANDLER_NOT_FOUND_EXCEPTION);
17: 		}
18: 		return Flux.fromIterable(this.handlerMappings)
19: 				.concatMap(mapping -> mapping.getHandler(exchange))
20: 				.next()
21: 				.switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION))
22: 				.flatMap(handler -> invokeHandler(exchange, handler))
23: 				.flatMap(result -> handleResult(exchange, result));
24: 	}
25: }

第 18 至 20 行 :順序使用 handlerMappings 獲得對應的 WebHandler 。
使用 #concatMap(Function) 操作符的原因是考慮 handlerMappings 的順序性,具體作用是將所有handlermapping按照順序組合起來 。然後,遍歷所有handlermapping,找到公共抽象類AbstractHandlerMapping,該類有getHandler(ServerWebExchange exchange)方法,該方法會調用所有HandlerMapping的getHandlerInternal方法(目前發現只有RouterFunctionMapping和RoutePredicateHandlerMapping有該方法)。
使用官方 spring-cloud-gateway-sample 項目,此處打斷點,handlerMappings 變量值如下圖 :
在這裏插入圖片描述
第 19 行,調用 HandlerMapping#getHandler(ServerWebExchange) 獲得 Handler 。在整理,RoutePredicateHandlerMapping 匹配請求對應的 Route ,並返回 FilteringWebHandler 。此時,FilteringWebHandler 還並未獲得 Route 的 GatewayFilter ,創建 GatewayFilterChain 處理請求。

第 21 行 :如果匹配不到 WebHandler ,返回 HANDLER_NOT_FOUND_EXCEPTION 。

第 22 行 :調用 #handle() 方法,執行 Handler 。代碼如下 :

 1: private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
 2: 	if (this.handlerAdapters != null) {
 3: 		for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
 4: 			if (handlerAdapter.supports(handler)) {
 5: 				return handlerAdapter.handle(exchange, handler);
 6: 			}
 7: 		}
 8: 	}
 9: 	return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
10: }

使用官方 spring-cloud-gateway-sample 項目,此處打斷點,handlerMappings 變量值如下圖 :
在這裏插入圖片描述
第 2 至 8 行 :順序匹配 HandlerAdapter ,通過調用 HandlerAdapter#handle(ServerWebExchange, Object) 方法,從而執行 Handler 。在此處,我們會匹配到 SimpleHandlerAdapter 。
第 9 行 :匹配不到 HandlerAdapter ,返回 IllegalStateException 。
第 23 行 :調用 #handleResult() 方法,處理結果。SimpleHandlerAdapter 返回的是 Mono.empty() ,所以不會觸發該方法。#handleResult() 代碼如下 :

1: private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
2: 	return getResultHandler(result).handleResult(exchange, result)
3: 			.onErrorResume(ex -> result.applyExceptionHandler(ex).flatMap(exceptionResult ->
4: 					getResultHandler(exceptionResult).handleResult(exchange, exceptionResult)));
5: }

3.3 SimpleHandlerAdapter

org.springframework.web.reactive.result.SimpleHandlerAdapter ,執行 WebHandler 的處理器適配器。
#handle(ServerWebExchange, Object) 方法,代碼如下 :

1: @Override
2: public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
3: 	WebHandler webHandler = (WebHandler) handler;
4: 	Mono<Void> mono = webHandler.handle(exchange);
5: 	return mono.then(Mono.empty());
6: }

第 3 至 4 行 :調用 WebHandler#handle(ServerWebExchange) 方法,執行處理器。例如,WebHandler 爲 FilteringWebHandler 時,獲得 Route 的 GatewayFilter 數組,創建 GatewayFilterChain 處理請求。
第 5 行 :在 WebHandler 執行完後 ( #then(Mongo) ),然後返回 Mono.empty() 。

3.4 RoutePredicateHandlerMapping

org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping ,匹配 Route ,並返回處理 Route 的 FilteringWebHandler 。

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;

		setOrder(1); // RequestMappingHandlerMapping 之後
	}
}

調用 #setOrder(1) 的原因,Spring Cloud Gateway 的 GatewayWebfluxEndpoint 提供 HTTP API ,不需要經過網關,它通過 RequestMappingHandlerMapping 進行請求匹配處理。RequestMappingHandlerMapping 的 order = 0 ,需要排在 RoutePredicateHandlerMapping 前面。所以,RoutePredicateHandlerMapping 設置 order = 1 。
#getHandlerInternal() 方法,在 DispatcherHandler#handle(ServerWebExchange) 方法的【第 19 行】被調用,匹配 Route ,並返回處理 Route 的 FilteringWebHandler 。代碼如下 :

 1: @Override
 2: protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
 3:     // 設置 GATEWAY_HANDLER_MAPPER_ATTR 爲 RoutePredicateHandlerMapping
 4: 	exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName());
 5: 
 6: 	return lookupRoute(exchange) // 匹配 Route
 7: 			// .log("route-predicate-handler-mapping", Level.FINER) //name this
 8: 			.flatMap((Function<Route, Mono<?>>) r -> { // 返回 FilteringWebHandler
 9: 				if (logger.isDebugEnabled()) {
10: 					logger.debug("Mapping [" + getExchangeDesc(exchange) + "] to " + r);
11: 				}
12: 
13: 				// 設置 GATEWAY_ROUTE_ATTR 爲 匹配的 Route
14: 				exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
15: 				// 返回
16: 				return Mono.just(webHandler);
17: 			}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> { // 匹配不到 Route
18: 				if (logger.isTraceEnabled()) {
19: 					logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]");
20: 				}
21: 			})));
22: }

第 4 行 :設置 GATEWAY_HANDLER_MAPPER_ATTR 爲 RoutePredicateHandlerMapping 。
第 6 行 :調用 #lookupRoute(ServerWebExchange) 方法,匹配 Route 。
第 8 至 16 行 :返回 Route 的處理器 FilteringWebHandler 。
第 14 行 :設置 GATEWAY_ROUTE_ATTR 爲匹配的 Route 。
第 16 行 :返回 FilteringWebHandler。
第 17 至 21 行 :匹配不到 Route ,返回 Mono.empty() ,即不返回處理器。這樣會不會有問題?不會,在 DispatcherHandler#handle(ServerWebExchange) 方法的【第 21 行】,我們可以看到,當沒有合適的 Handler ,返回 Mono.error(HANDLER_NOT_FOUND_EXCEPTION) 。
#lookupRoute(ServerWebExchange) 方法,順序匹配 Route 。代碼如下 :

 1: protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
 2: 	return this.routeLocator.getRoutes()
 3: 			.filter(route -> route.getPredicate().test(exchange))
 4: 			.next()
 5: 			//TODO: error handling
 6: 			.map(route -> {
 7: 				if (logger.isDebugEnabled()) {
 8: 					logger.debug("RouteDefinition matched: " + route.getId());
 9: 				}
10: 				validateRoute(route, exchange);
11: 				return route;
12: 			});
13: }

第 2 至 4 行 :調用 RouteLocator#getRoutes() 方法,獲得全部 Route ,並調用 Predicate#test(ServerWebExchange) 方法,順序匹配一個 Route。
第 5 行 :未來會增加匹配過程中發生異常的處理。目前,任何一個 Predicate#test(ServerWebExchange) 的方法調用發生異常時,都會導致匹配不到 Route 。一定要注意。
第 6 至 11 行 :調用 #validateRoute(Route, ServerWebExchange) 方法,校驗 Route 的有效性。目前該方法是個空方法,可以通過繼承 RoutePredicateHandlerMapping 進行覆蓋重寫。

3.5 FilteringWebHandler

在 SimpleHandlerAdapter 裏,我們看到 SimpleHandlerAdapter#handle(ServerWebExchange, Object) 調用 FilteringWebHandler#handle(ServerWebExchange) 方法,處理請求。
FilteringWebHandler 通過創建請求對應的 Route 對應的 GatewayFilterChain 進行處理。
org.springframework.cloud.gateway.handler.FilteringWebHandler ,#handle(ServerWebExchange) 代碼如下 :

1: public class FilteringWebHandler implements WebHandler {
 2: 
 3: 	/**
 4: 	 * 全局過濾器
 5: 	*/
 6: 	private final List<GatewayFilter> globalFilters;
 7: 
 8: 	@Override
 9: 	public Mono<Void> handle(ServerWebExchange exchange) {
10: 	    // 獲得 Route
11: 		Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
12: 		// 獲得 GatewayFilter
13: 		List<GatewayFilter> gatewayFilters = route.getFilters();
14: 		List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
15: 		combined.addAll(gatewayFilters);
16: 
17: 		// 排序
18: 		//TODO: needed or cached?
19: 		AnnotationAwareOrderComparator.sort(combined);
20: 		logger.debug("Sorted gatewayFilterFactories: "+ combined);
21: 
22: 		// 創建 DefaultGatewayFilterChain
23: 		return new DefaultGatewayFilterChain(combined).filter(exchange);
24: 	}
25: }

本方法涉及到的過濾器 GlobalFilter / GatewayFilter / GatewayFilterAdapter / OrderedGatewayFilter 類,參考芋道源碼《Spring-Cloud-Gateway 源碼解析 —— 過濾器 (4.1) 之 GatewayFilter 一覽》 詳細解析。
第 11 行 :從 GATEWAY_ROUTE_ATTR 獲得 請求對應的 Route 。
第 13 至 15 行 :獲得 GatewayFilter 數組,包含 route.filters 和 globalFilters 。
第 19 行 :排序獲得的 GatewayFilter 數組。
第 23 行 :使用獲得的 GatewayFilter 數組創建 DefaultGatewayFilterChain ,過濾處理請求。

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