spring cloud gateway 工作过程

Last Modified: 2023/02/08

概述

Spring Cloud Gateway 是一个构建在 Java 和 spring 框架之上的 API 网关的库。路由方式灵活,可编程可配置,利用网关的全局可以实现统一的身份认证等功能,今天我们从高层视角看 spring cloud 是如何工作的。

官方提供的工作流程图

Clients make requests to Spring Cloud Gateway. If the Gateway Handler Mapping determines that a request matches a route, it is sent to the Gateway Web Handler. This handler runs the request through a filter chain that is specific to the request. The reason the filters are divided by the dotted line is that filters can run logic both before and after the proxy request is sent. All “pre” filter logic is executed. Then the proxy request is made. After the proxy request is made, the “post” filter logic is run.

翻译过来就是:一个请求经过 handler mapping 来匹配路由和路由处理器,然后请求被交给处理器处理。处理过程为:请求沿着一系列过滤器处理之后,最终到达目标服务,响应则反向经过这一系列的过滤器处理之后返回客户端。

更丰富处理流程图

官方流程图过于简洁,我们需要丰富下官方流程图,以便更好的理解请求的处理流程:

在 spring cloud gateway 中使用 ServerWebExchange 对象代表客户端请求,请求大的处理过程如下:

  • ①请求被 DispatcherHandler#handle 方法处理;
  • ②该方法会遍历所有的 handler mappings 对象,目的是通过调用该对象的 getHandler 方法获取可以处理该请求的 Handler;
  • ③通过上一步的 handler 的 handle 方法处理请求。

其中步骤②是关键点,这里有一个很重要的 Handler mapping 对象: RoutePredicateHandlerMapping,该对象的 getHandler 方法会遍历我们配置的路由,依次调用每个路由相关的 GatewayPredicate 对象的 test 方法测试路由是否匹配,如果匹配就将该路由对象放到 ServerWebExchange 对象的属性中,同时返回 FilteringWebHandler 对象。

一般我们在配置中心配置路由:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          lowerCaseServiceId: true
          enabled: true
      routes:
        - id: order-service
          uri: lb://order-serivce
          predicates:
            - Path=/order/**
          filters:
            - CacheRequestFilter
            - ValidateCodeFilter
            - StripPrefix=1

上面我们配置了一个路由,id 为 order-service,路由断言为 Path=/order/**,同时还给路由配置了3个 filter。

通过上面的说明我们知道,如果某个路由的 GatewayPredicate#test 方法返回了 true,那么请求会被交给 FilteringWebHandler 对象处理,该对象处理请求的过程如下:

  • ①从请求对象(exchange)中获取路由对象;
  • ②获取路由的配置的 filters 和全局 filters,排序这些 filters 之后,让请求依次通过这些 filters 处理。

FilteringWebHandler#handlle 方法如下:

@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);
  // TODO: needed or cached?
  AnnotationAwareOrderComparator.sort(combined);

  if (logger.isDebugEnabled()) {
      logger.debug("Sorted gatewayFilterFactories: " + combined);
  }

  return new DefaultGatewayFilterChain(combined).filter(exchange);
}
有问题吗?点此反馈!

温馨提示:反馈需要登录