004-spring cloud gateway-網關請求處理過程


一、網關請求處理過程

   

  客戶端向Spring Cloud Gateway發出請求。如果網關處理程序映射確定請求與路由匹配,則將其發送到網關Web處理程序。此處理程序運行通過特定於請求的過濾器鏈發送請求。濾波器被虛線划分的原因是濾波器可以在發送代理請求之前或之后執行邏輯。執行所有“pre”過濾器邏輯,然后進行代理請求。在發出代理請求之后,執行“post”過濾器邏輯。

   在沒有端口的路由中定義的URI將分別為HTTP和HTTPS URI獲取默認端口設置為80和443。

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

1.1、DispatcherHandler分發處理

在import org.springframework.web.reactive.DispatcherHandler;類中核心方法handle
    public Mono<Void> handle(ServerWebExchange exchange) {
        if (logger.isDebugEnabled()) { ServerHttpRequest request = exchange.getRequest(); logger.debug("Processing " + request.getMethodValue() + " request for [" + request.getURI() + "]"); } //校驗handlerMapping集合是否為空 //依次遍歷handlerMapping集合進行請求處理 //通過mapping獲取mapping對應的handler,調用handler處理 return this.handlerMappings == null ? Mono.error(HANDLER_NOT_FOUND_EXCEPTION) : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> { return mapping.getHandler(exchange); }).next().switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION)).flatMap((handler) -> { return this.invokeHandler(exchange, handler); }).flatMap((result) -> { return this.handleResult(exchange, result); }); } 

DispatcherHandler的handler執行順序

  • 校驗handlerMapping
  • 遍歷Mapping獲取mapping對應的handler(此處會找到gateway對應的 RoutePredicateHandlerMapping,並通過 RoutePredicateHandlerMapping獲取handler(FilteringWebHandler))
  • 通過handler對應的HandlerAdapter對handler進行調用(gateway使用的 SimpleHandlerAdapter) 即 FilteringWebHandler與SimpleHandlerAdapter對應
  

其中SimpleHandlerAdapter中handler實現

    public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
        WebHandler webHandler = (WebHandler)handler; Mono<Void> mono = webHandler.handle(exchange); return mono.then(Mono.empty()); }

1.2、RoutePredicateHandlerMapping 路由謂詞處理映射

public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
    private final FilteringWebHandler webHandler; private final RouteLocator routeLocator; public RoutePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties) { this.webHandler = webHandler; this.routeLocator = routeLocator; //設置排序字段1,此處的目的是Spring Cloud Gateway 的 GatewayWebfluxEndpoint 提供 HTTP API ,不需要經過網關 //它通過 RequestMappingHandlerMapping 進行請求匹配處理。RequestMappingHandlerMapping 的 order = 0 , // 需要排在 RoutePredicateHandlerMapping 前面。所有,RoutePredicateHandlerMapping 設置 order = 1 。 this.setOrder(1); this.setCorsConfigurations(globalCorsProperties.getCorsConfigurations()); } protected Mono<?> getHandlerInternal(ServerWebExchange exchange) { //設置mapping到上下文環境 exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_HANDLER_MAPPER_ATTR, this.getClass().getSimpleName()); // 查找路由 return this.lookupRoute(exchange).flatMap((r) -> { exchange.getAttributes().remove(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR); if (this.logger.isDebugEnabled()) { this.logger.debug("Mapping [" + this.getExchangeDesc(exchange) + "] to " + r); } //將找到的路由信息設置到上下文環境中  exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR, r); //返回mapping對應的WebHandler即FilteringWebHandler return Mono.just(this.webHandler); }).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> { //當前未找到路由時返回空,並移除GATEWAY_PREDICATE_ROUTE_ATTR  exchange.getAttributes().remove(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR); if (this.logger.isTraceEnabled()) { this.logger.trace("No RouteDefinition found for [" + this.getExchangeDesc(exchange) + "]"); } }))); } protected CorsConfiguration getCorsConfiguration(Object handler, ServerWebExchange exchange) { return super.getCorsConfiguration(handler, exchange); } private String getExchangeDesc(ServerWebExchange exchange) { StringBuilder out = new StringBuilder(); out.append("Exchange: "); out.append(exchange.getRequest().getMethod()); out.append(" "); out.append(exchange.getRequest().getURI()); return out.toString(); } 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; }); } protected void validateRoute(Route route, ServerWebExchange exchange) { } }

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.3、FilteringWebHandler 過濾web請求處理

/**
 * 通過過濾器處理web請求的處理器
 */
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 */ 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); //對過濾器進行排序  AnnotationAwareOrderComparator.sort(combined); logger.debug("Sorted gatewayFilterFactories: "+ combined); //創建過濾器鏈表對其進行鏈式調用 return new DefaultGatewayFilterChain(combined).filter(exchange); } }

FilteringWebHandler的執行順序

  • 構建一個包含全局過濾器的集合(combined)
  • 獲取上下中的路由信息GATEWAY_ROUTE_ATTR
  • 將路由里的過濾器添加到集合中(combined)
  • 對過濾器集合進行排序操作
  • 通過過濾器集合組裝過濾器鏈表,並進行調用(DefaultGatewayFilterChain與Servlet中的FilterChain與原理是一致的)
  • 通過過濾器來處理請求到具體業務服務

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM