SpringCloud Gateway source code tracking analysis

1. Springcloud Gateway 

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

2. Core components:

Predicate

GetewayFilter

GlobalFilter

3. high-level overview

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/images/spring_cloud_gateway_diagram.png

3. Horizontal comparison with SpringMVC

SpringMVC =====> Spring WebFlux

DispatchServlet =====> DispatchHandler

Route matching:

HandlerMapping =====>HandlerMapping

HanderAdaper ====> HanderAdaper

Hander =====> WebHander

4. Source code tracking

Core class: org.springframework.web.reactive.DispatcherHandler

public Mono<Void> handle(ServerWebExchange exchange) {
    return this.handlerMappings == null ? this.createNotFoundError() : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> {
        return mapping.getHandler(exchange);
    }).next().switchIfEmpty(this.createNotFoundError()).flatMap((handler) -> {
        return this.invokeHandler(exchange, handler);
    }).flatMap((result) -> {
        return this.handleResult(exchange, result);
    });
}

org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping#getHandlerInternal

Execute all Predicate assertions in lookupRoute

protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
    return this.routeLocator.getRoutes().concatMap((route) -> {
        return Mono.just(route).filterWhen((r) -> {
            exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
            return (Publisher)r.getPredicate().apply(exchange);
        }).doOnError((e) -> {
            this.logger.error("Error applying predicate for route: " + route.getId(), e);
        }).onErrorResume((e) -> {
            return Mono.empty();
        });
    }).next().map((route) -> {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Route matched: " + route.getId());
        }

        this.validateRoute(route, exchange);
        return route;
    });
}

 org.springframework.cloud.gateway.handler.FilteringWebHandler#handle

Convert all GlobalFilters into Filters and add them to the filter chain

public Mono<Void> handle(ServerWebExchange exchange) {
    Route route = (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
    List<GatewayFilter> gatewayFilters = route.getFilters();
    List<GatewayFilter> combined = new ArrayList(this.globalFilters);
    combined.addAll(gatewayFilters);
    AnnotationAwareOrderComparator.sort(combined);
    if (logger.isDebugEnabled()) {
        logger.debug("Sorted gatewayFilterFactories: " + combined);
    }

    return (new FilteringWebHandler.DefaultGatewayFilterChain(combined)).filter(exchange);
}

 All filters

Core class org.springframework.cloud.gateway.filter.LoadBalancerClientFilter

ribbon finds the ip of the corresponding service based on serviceId

public Mono<Void> handle(ServerWebExchange exchange) {
    Route route = (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
    List<GatewayFilter> gatewayFilters = route.getFilters();
    List<GatewayFilter> combined = new ArrayList(this.globalFilters);
    combined.addAll(gatewayFilters);
    AnnotationAwareOrderComparator.sort(combined);
    if (logger.isDebugEnabled()) {
        logger.debug("Sorted gatewayFilterFactories: " + combined);
    }

    return (new FilteringWebHandler.DefaultGatewayFilterChain(combined)).filter(exchange);
}

Guess you like

Origin blog.csdn.net/caicongyang/article/details/126395670