Gateway

概念

  • Route: Route the basic building block of the gateway. It is defined by an ID, a destination URI, a collection of predicates and a collection of filters. A route is matched if aggregate predicate is true.react

    Route 是網關的基礎元素,由 ID、目標URI、斷言、過濾器 組成,請求到達網關時,由 Gateway Handler Mapping 經過斷言進行路由匹配(Mapping),當斷言爲真時,匹配到路由。web

  • Predicate: This is a Java 8 Function Predicate. The input type is a Spring Framework ServerWebExchange. This allows developers to match on anything from the HTTP request, such as headers or parameters.spring

    Predicate 屬於Java8,我習慣稱之爲斷言,或者條件。app

  • Filter: These are instances Spring Framework GatewayFilter constructed in with a specific factory. Here, requests and responses can be modified before or after sending the downstream request.cors

    Filter 過濾器。async

請求處理過程

Spring Cloud Gateway 基於 Spring WebFlux,和Spring Web MVC相似,每一個請求經過 HandlerMapping 打到具體的 Handler 上(Handler/Controller)。ide

public interface HandlerMapping {
	Mono<Object> getHandler(ServerWebExchange exchange);
}
public abstract class AbstractHandlerMapping extends ApplicationObjectSupport implements HandlerMapping, Ordered {

	@Override
	public Mono<Object> getHandler(ServerWebExchange exchange) {
	
	    // 獲取handler,並校驗cors,此處爲僞代碼
    	return getHandlerInternal(exchange).map(handler -> isCorsRequest)
	}

	protected abstract Mono<?> getHandlerInternal(ServerWebExchange exchange);
}
public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {

	private final FilteringWebHandler webHandler;

	private final RouteLocator routeLocator;
	
	@Override
	protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
        
        return lookupRoute(exchange)
				.flatMap((Function<Route, Mono<?>>) r -> {
				
				    // 網關的 Filter Chain
					return Mono.just(webHandler);
				})
	}
	
	// 獲取並匹配路由
	protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
	    
	    return this.routeLocator.getRoutes()
				.filterWhen(route ->  {
				
				    // 經過 Predicate 匹配路由
					return route.getPredicate().apply(exchange);
				})
	}
}

AbstractHandlerMapping的實現類以下ui

一個web應用有多個handlerMapping,Spring WebFlux經過org.springframework.web.reactive.DispatcherHandler來分發請求到HandlerMapping,而後Mapping到handler上面。this

public class DispatcherHandler implements WebHandler, ApplicationContextAware {

	@Nullable
	private List<HandlerMapping> handlerMappings;
	
	@Override
	public Mono<Void> handle(ServerWebExchange exchange) {
	    
	    
		return Flux.fromIterable(this.handlerMappings)
				.concatMap(mapping -> mapping.getHandler(exchange))         // 遍歷 handlerMappings#getHandler
				.next()
				.switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION))
				.flatMap(handler -> invokeHandler(exchange, handler))       // 調用 handler
				.flatMap(result -> handleResult(exchange, result));         // 處理結果
	}
}

獲取路由過程

由上可見,經過 RouteLocator 獲取 Route 時。spa

public interface RouteLocator {

	Flux<Route> getRoutes();
}

經過Debug,RoutePredicateHandlerMapping中routeLocator的實例是 CachingRouteLocator

public class CachingRouteLocator implements RouteLocator {

	private final RouteLocator delegate;

	private final Flux<Route> routes;
		
	private final Map<String, List> cache = new HashMap<>();

	@Override
	public Flux<Route> getRoutes() {
		return this.routes;
	}
}

RoutePredicateHandlerMapping.routeLocator的實例是CachingRouteLocator,網關啓動後,第一次請求,因爲沒有cache,所以向delegate(代理)尋求routes。

這個代理的實例是 RouteDefinitionRouteLocator。

public class RouteDefinitionRouteLocator implements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware {

	private final RouteDefinitionLocator routeDefinitionLocator;

	@Override
	public Flux<Route> getRoutes() {
	
	    // 獲取路由定義,並轉換爲路由
		return this.routeDefinitionLocator.getRouteDefinitions()
				.map(this::convertToRoute)
    }
    
    // RouteDefine -> Route
	private Route convertToRoute(RouteDefinition routeDefinition) {
	
    	AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
    	List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);

        // Route 的 AsyncBuilder
		return Route.async(routeDefinition)
				.asyncPredicate(predicate)
				.replaceFilters(gatewayFilters)
				.build();
	}
}
public interface RouteDefinitionLocator {

	Flux<RouteDefinition> getRouteDefinitions();
}

相關文章
相關標籤/搜索