SpringCloudGateway源码阅读(一)核心概念及路由加载

一、核心概念

路由Route

路由是网关的核心抽象。

public class Route implements Ordered {
    // 唯一id
    private final String id;
    // 跳转uri
    private final URI uri;
    // SpringBean优先级
    private final int order;
    // 断言
    private final AsyncPredicate<ServerWebExchange> predicate;
    // 当前路由特有的过滤器
    private final List<GatewayFilter> gatewayFilters;
    // 元数据
    private final Map<String, Object> metadata;
}
复制代码

ServerWebExchange

ServerWebExchange是spring-web的一个接口,提供ServerHttpRequest、ServerHttpResponse,ApplicationContext等实例的get方法。

断言AsyncPredicate

断言用于判断路由是否匹配某个ServerWebExchange。

public interface AsyncPredicate<T> extends Function<T, Publisher<Boolean>> {
    // 构造与AsyncPredicate
    default AsyncPredicate<T> and(AsyncPredicate<? super T> other) {
        return new AndAsyncPredicate<>(this, other);
    }
    // 构造非AsyncPredicate
    default AsyncPredicate<T> negate() {
        return new NegateAsyncPredicate<>(this);
    }
    // 构造或AsyncPredicate
    default AsyncPredicate<T> or(AsyncPredicate<? super T> other) {
        return new OrAsyncPredicate<>(this, other);
    }
    // 构造默认AsyncPredicate
    static AsyncPredicate<ServerWebExchange> from(
            Predicate<? super ServerWebExchange> predicate) {
        return new DefaultAsyncPredicate<>(GatewayPredicate.wrapIfNeeded(predicate));
    }
    // 默认AsyncPredicate
    class DefaultAsyncPredicate<T> implements AsyncPredicate<T> {

        private final Predicate<T> delegate;

        public DefaultAsyncPredicate(Predicate<T> delegate) {
            this.delegate = delegate;
        }

        @Override
        public Publisher<Boolean> apply(T t) {
            return Mono.just(delegate.test(t));
        }

    }
    // 非AsyncPredicate
    class NegateAsyncPredicate<T> implements AsyncPredicate<T> {

        private final AsyncPredicate<? super T> predicate;

        public NegateAsyncPredicate(AsyncPredicate<? super T> predicate) {
            this.predicate = predicate;
        }

        @Override
        public Publisher<Boolean> apply(T t) {
            return Mono.from(predicate.apply(t)).map(b -> !b);
        }

    }
    // 与AsyncPredicate
    class AndAsyncPredicate<T> implements AsyncPredicate<T> {

        private final AsyncPredicate<? super T> left;

        private final AsyncPredicate<? super T> right;

        public AndAsyncPredicate(AsyncPredicate<? super T> left,
                AsyncPredicate<? super T> right) {
            this.left = left;
            this.right = right;
        }

        @Override
        public Publisher<Boolean> apply(T t) {
            return Mono.from(left.apply(t)).flatMap(
                    result -> !result ? Mono.just(false) : Mono.from(right.apply(t)));
        }
    }
    // 或AsyncPredicate
    class OrAsyncPredicate<T> implements AsyncPredicate<T> {

        private final AsyncPredicate<? super T> left;

        private final AsyncPredicate<? super T> right;

        public OrAsyncPredicate(AsyncPredicate<? super T> left,
                AsyncPredicate<? super T> right) {
            this.left = left;
            this.right = right;
        }

        @Override
        public Publisher<Boolean> apply(T t) {
            return Mono.from(left.apply(t)).flatMap(
                    result -> result ? Mono.just(true) : Mono.from(right.apply(t)));
        }

    }

}
复制代码

路由过滤器GatewayFilter

针对于路由的过滤器,无法离开Route而存在。

public interface GatewayFilter extends ShortcutConfigurable {
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
复制代码

全局过滤器GlobalFilter

全局的过滤器,所有路由都必须执行的过滤器。后续Bean实例化的时候,会适配成GatewayFilter被使用。

public interface GlobalFilter {
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
复制代码

过滤器链GatewayFilterChain

GatewayFilterChain过滤器链允许GatewayFilter过滤器按顺序,挨个执行。

public interface GatewayFilterChain {
    Mono<Void> filter(ServerWebExchange exchange);
}
复制代码

路由定义RouteDefinition

类似于Spring的BeanDefinition,Route的一种构建方式就是通过RouteDefinition,比如从properties文件中解析得到的路由规则定义。

public class RouteDefinition {
    // 唯一id
    private String id;
        // 断言定义
    private List<PredicateDefinition> predicates = new ArrayList<>();
    // 过滤器定义
    private List<FilterDefinition> filters = new ArrayList<>();
    // 跳转uri
    private URI uri;
    // 元数据
    private Map<String, Object> metadata = new HashMap<>();
    // Spring优先级
    private int order = 0;
}
复制代码

断言定义PredicateDefinition

从配置文件加载的断言定义,构造Route时,会用RoutePredicateFactory#applyAsync转换成AsyncPredicate。

public class PredicateDefinition {
    private String name;
    private Map<String, String> args = new LinkedHashMap<>();
    public PredicateDefinition() {
    }
    // predicates:
    //     - Path=/echo // 解析'Path=/echo'放入args
    public PredicateDefinition(String text) {
        int eqIdx = text.indexOf('=');
        // 设置name
        setName(text.substring(0, eqIdx));
    
        String[] args = tokenizeToStringArray(text.substring(eqIdx + 1), ",");
        // 设置args
        for (int i = 0; i < args.length; i++) {
            this.args.put(NameUtils.generateName(i), args[i]);
        }
    }
}
复制代码

路由过滤器定义FilterDefinition

从配置文件加载的路由过滤器定义,构造Route时,会用GatewayFilterFactory#apply转换为GatewayFilter。

public class FilterDefinition {
    private String name;
    private Map<String, String> args = new LinkedHashMap<>();
    public FilterDefinition() {
    }
    // 解析配置文件 PrefixPath=/httpbin
    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]);
        }
    }
}
复制代码

获取路由定义RouteDefinitionLocator

RouteDefinitionLocator具有获取路由定义的能力。

public interface RouteDefinitionLocator {
    Flux<RouteDefinition> getRouteDefinitions();
}
复制代码

最后对外暴露的实际是CompositeRouteDefinitionLocator,他组合了所有RouteDefinitionLocator。

获取路由RouteLocator

RouteLocator具有获取路由Route的能力。网关处理请求时只会调用RouteLocator获取Route,通过Route的断言和过滤处理请求。

public interface RouteLocator {
    Flux<Route> getRoutes();
}
复制代码

Spring容器加载的时候,会把路由都放到CachingRouteLocator里,后续运行时只会和CachingRouteLocator打交道。

二、加载路由

讲解从Gateway的Bean装配,到加载Route到CachingRouteLocator。

自动配置

Spring-Cloud-Gateway的自动配置类是org.springframework.cloud.gateway.config.GatewayAutoConfiguration。重点看一些重要的Bean装配,全局Filter等下一章节讲请求流程的时候再分析。

Gateway配置文件

@Bean
public GatewayProperties gatewayProperties() {
    return new GatewayProperties();
}
@ConfigurationProperties("spring.cloud.gateway")
@Validated
public class GatewayProperties {
    // 路由
    private List<RouteDefinition> routes = new ArrayList<>();
    // 默认过滤器
    private List<FilterDefinition> defaultFilters = new ArrayList<>();
}
复制代码

RouteDefinitionLocator相关

  • PropertiesRouteDefinitionLocator:配置文件创建RouteDefinitionLocator
@Bean
@ConditionalOnMissingBean
public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(
        GatewayProperties properties) {
    return new PropertiesRouteDefinitionLocator(properties);
}
复制代码
  • InMemoryRouteDefinitionRepository:内存级别路由定义,无法持久化,支持动态新增和删除路由定义
@Bean
@ConditionalOnMissingBean(RouteDefinitionRepository.class)
public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
    return new InMemoryRouteDefinitionRepository();
}
复制代码
  • CompositeRouteDefinitionLocator:组合其他所有的RouteDefinitionLocator,并且是Primary的
@Bean
@Primary
public RouteDefinitionLocator routeDefinitionLocator(
        List<RouteDefinitionLocator> routeDefinitionLocators) {
    return new CompositeRouteDefinitionLocator(
            Flux.fromIterable(routeDefinitionLocators));
}
复制代码

RouteLocator相关

  • RouteLocatorBuilder:辅助用编码方式注入自定义的RouteLocator。
@Bean
public RouteLocatorBuilder routeLocatorBuilder(
        ConfigurableApplicationContext context) {
    return new RouteLocatorBuilder(context);
}
复制代码
  • RouteDefinitionRouteLocator:用RouteDefinitionLocator和GatewayFilterFactory和RoutePredicateFactory构造Route,创建RouteLocator。
@Bean
public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
        List<GatewayFilterFactory> gatewayFilters,
        List<RoutePredicateFactory> predicates,
        RouteDefinitionLocator routeDefinitionLocator,
        ConfigurationService configurationService) {
    return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates,
            gatewayFilters, properties, configurationService);
}
复制代码
  • CachingRouteLocator:委托CompositeRouteLocator聚合其他所有RouteLocator,实现RouteLocator。
@Bean
@Primary
@ConditionalOnMissingBean(name = "cachedCompositeRouteLocator")
public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
    return new CachingRouteLocator(
            new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
}
复制代码

加载路由入口类RouteRefreshListener

@Bean
public RouteRefreshListener routeRefreshListener(ApplicationEventPublisher publisher) {
    return new RouteRefreshListener(publisher);
}
复制代码

加载路由到CachingRouteLocator

RouteRefreshListener

加载路由到RouteLocator的入口,通过Spring事件触发。

public class RouteRefreshListener implements ApplicationListener<ApplicationEvent> {

    private final ApplicationEventPublisher publisher;

    public RouteRefreshListener(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent
                || event instanceof RefreshScopeRefreshedEvent
                || event instanceof InstanceRegisteredEvent) {
            reset();
        }
        // ... 省略其他事件判断,也可能触发reset
    }
    
    // 发布RefreshRoutesEvent事件
    private void reset() {
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

}
复制代码

CachingRouteLocator

CachingRouteLocator收到RefreshRoutesEvent,委托CompositeRouteLocator获取Flux<Route>放入自己的缓存cache中。

public class CachingRouteLocator implements Ordered, RouteLocator,
        ApplicationListener<RefreshRoutesEvent>, ApplicationEventPublisherAware {
    // 写死的缓存cache的key
    private static final String CACHE_KEY = "routes";
    // CompositeRouteLocator
    private final RouteLocator delegate;
    // Route列表
    private final Flux<Route> routes;
    // 缓存
    private final Map<String, List> cache = new ConcurrentHashMap<>();
    // 事件发布者
    private ApplicationEventPublisher applicationEventPublisher;

    public CachingRouteLocator(RouteLocator delegate) {
        this.delegate = delegate;
        // 这里并不会触发fetch,只有当需要routes的时候才会触发fetch,比如getRoutes()
        routes = CacheFlux.lookup(cache, CACHE_KEY, Route.class)
                .onCacheMissResume(this::fetch);
    }
    // 委托CompositeRouteLocator获取Route并排序
    private Flux<Route> fetch() {
        return this.delegate.getRoutes().sort(AnnotationAwareOrderComparator.INSTANCE);
    }
    // 获取Route,如果routes为空,会触发fetch
    @Override
    public Flux<Route> getRoutes() {
        return this.routes;
    }
    // 清空缓存
    public Flux<Route> refresh() {
        this.cache.clear();
        return this.routes;
    }
    // 接收RefreshRoutesEvent
    @Override
    public void onApplicationEvent(RefreshRoutesEvent event) {
        try {
            // 委托CompositeRouteLocator获取Route并排序
            fetch()
            .collect(Collectors.toList())
            .subscribe(list -> Flux.fromIterable(list)
                  .materialize().collect(Collectors.toList()).subscribe(signals -> {
                      applicationEventPublisher.publishEvent(new RefreshRoutesResultEvent(this));
                      // 放入缓存
                      cache.put(CACHE_KEY, signals);
                  }, throwable -> handleRefreshError(throwable)));
        }
        catch (Throwable e) {
            handleRefreshError(e);
        }
    }
    // 发生异常发布RefreshRoutesResultEvent事件
    private void handleRefreshError(Throwable throwable) {
        applicationEventPublisher
                .publishEvent(new RefreshRoutesResultEvent(this, throwable));
    }
    void handleRefresh() {
        refresh();
    }
    @Override
    public int getOrder() {
        return 0;
    }
    @Override
    public void setApplicationEventPublisher(
            ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }
}
复制代码

CompositeRouteLocator

通过其他RouteLocator获取所有Route。

public class CompositeRouteLocator implements RouteLocator {
    // 其他所有RouteLocator,除了CachingRouteLocator
    private final Flux<RouteLocator> delegates;
    public CompositeRouteLocator(Flux<RouteLocator> delegates) {
        this.delegates = delegates;
    }
    @Override
    public Flux<Route> getRoutes() {
        return this.delegates.flatMapSequential(RouteLocator::getRoutes);
    }
}
复制代码

1 编码方式获取Route

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
            .route(r -> r.host("**.abc.org").and().path("/anything/png")
                .filters(f ->
                        f.prefixPath("/httpbin")
                                .addResponseHeader("X-TestHeader", "foobar"))
                .uri(uri)
            )
            .build();
}
复制代码

RouteLocatorBuilder.Builder构造的RouteLocator,Bean注入的时候直接构造完成了。具体构造过程不细看了,也是利用了RoutePredicateFactory和GatewayFilterFactory。

public static class Builder {
    private List<Route.AsyncBuilder> routes = new ArrayList<>();
    public RouteLocator build() {
        return () -> Flux.fromIterable(this.routes)
                .map(routeBuilder -> routeBuilder.build());
    }
复制代码

2 RouteDefinitionRouteLocator

RouteDefinitionRouteLocator只负责通过RouteDefinition创建Route,委托CompositeRouteDefinitionLocator获取RouteDefinition,并通过ConfigurationService、RoutePredicateFactory、GatewayFilterFactory将RouteDefinition转换为Route返回。

public class RouteDefinitionRouteLocator
        implements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware {
    // 默认过滤器名字
    public static final String DEFAULT_FILTERS = "defaultFilters";
    // 委托CompositeRouteDefinitionLocator
    private final RouteDefinitionLocator routeDefinitionLocator;
    // ConfigurationService操作RoutePredicateFactory和GatewayFilterFactory
    // 转换断言和过滤器
    private final ConfigurationService configurationService;
    // name - RoutePredicateFactory
    private final Map<String, RoutePredicateFactory> predicates = new LinkedHashMap<>();
    // name - GatewayFilterFactory
    private final Map<String, GatewayFilterFactory> gatewayFilterFactories = new HashMap<>();
    // spring.cloud.gateway配置文件
    private final GatewayProperties gatewayProperties;
    
    @Override
    public Flux<Route> getRoutes() {
        Flux<Route> routes = this.routeDefinitionLocator
                // 委托CompositeRouteDefinitionLocator获取RouteDefinition
                .getRouteDefinitions()
                // 转换为Route
                .map(this::convertToRoute);
        // 如果spring.cloud.gateway.failOnRouteDefinitionError=true(默认)
        // 仅仅打印日志
        if (!gatewayProperties.isFailOnRouteDefinitionError()) {
            routes = routes.onErrorContinue((error, obj) -> {
                    logger.warn(...);
            });
        }
        return routes;
    }
}
复制代码
  • CompositeRouteDefinitionLocator

getRouteDefinitions循环所有RouteDefinitionLocator获取所有RouteDefinition。

public class CompositeRouteDefinitionLocator implements RouteDefinitionLocator {
  private final Flux<RouteDefinitionLocator> delegates;
  private final IdGenerator idGenerator;
  public CompositeRouteDefinitionLocator(Flux<RouteDefinitionLocator> delegates) {
      this(delegates, new AlternativeJdkIdGenerator());
  }
  public CompositeRouteDefinitionLocator(Flux<RouteDefinitionLocator> delegates,
          IdGenerator idGenerator) {
      this.delegates = delegates;
      this.idGenerator = idGenerator;
  }

  @Override
  public Flux<RouteDefinition> getRouteDefinitions() {
      return this.delegates
              // 委托所有其他RouteDefinitionLocator获取RouteDefinition
              .flatMapSequential(RouteDefinitionLocator::getRouteDefinitions)
              .flatMap(routeDefinition -> {
                  // 如果RouteDefinition没有设置id,随便给一个
                  if (routeDefinition.getId() == null) {
                      return randomId().map(id -> {
                          routeDefinition.setId(id);
                          return routeDefinition;
                      });
                  }
                  return Mono.just(routeDefinition);
              });
  }
  // 获取随机id
  protected Mono<String> randomId() {
      return Mono.fromSupplier(idGenerator::toString)
              .publishOn(Schedulers.boundedElastic());
  }
}
复制代码

RouteDefinitionLocator有很多种,以PropertiesRouteDefinitionLocator为例。

public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator {
  private final GatewayProperties properties;
  public PropertiesRouteDefinitionLocator(GatewayProperties properties) {
      this.properties = properties;
  }
  @Override
  public Flux<RouteDefinition> getRouteDefinitions() {
      return Flux.fromIterable(this.properties.getRoutes());
  }
}
复制代码
  • RouteDefinitionRouteLocator.convertToRoute

通过ConfigurationService、RoutePredicateFactory、GatewayFilterFactory将RouteDefinition转换为Route。

private Route convertToRoute(RouteDefinition routeDefinition) {
  // 将routeDefinition里的PredicateDefinition
  // 通过RoutePredicateFactory转换为AsyncPredicate
  AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
  // 将routeDefinition里的FilterDefinition
  // 通过GatewayFilterFactory转换为GatewayFilter
  List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);
  // 组装Route
  return Route.async(routeDefinition).asyncPredicate(predicate)
          .replaceFilters(gatewayFilters).build();
}
复制代码

RouteDefinitionRouteLocator#combinePredicates转换PredicateDefinition为AsyncPredicate。

private AsyncPredicate<ServerWebExchange> combinePredicates(
            RouteDefinition routeDefinition) {
    List<PredicateDefinition> predicates = routeDefinition.getPredicates();
    // 先获取第一个断言定义,转换为AsyncPredicate
    AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition,
            predicates.get(0));
    // 后续定义用and连接
    for (PredicateDefinition andPredicate : predicates.subList(1,
            predicates.size())) {
        AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition,
                andPredicate);
        predicate = predicate.and(found);
    }
    return predicate;
}
private AsyncPredicate<ServerWebExchange> lookup(RouteDefinition route,
            PredicateDefinition predicate) {
  // 通过PredicateDefinition的name找到对应的RoutePredicateFactory
  RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName());
  // ConfigurationService操作RouteDefinition和RoutePredicateFactory
  Object config = this.configurationService.with(factory)
          .name(predicate.getName())
          .properties(predicate.getArgs())
          .eventFunction((bound, properties) -> new PredicateArgsEvent(
                  RouteDefinitionRouteLocator.this, route.getId(), properties))
          .bind();
  return factory.applyAsync(config);
}
复制代码

RouteDefinitionRouteLocator#getFilters将FilterDefinition转换为GatewayFilter。

private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {
  List<GatewayFilter> filters = new ArrayList<>();
  // 如果默认过滤器不为空,加入默认过滤器
  if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
      filters.addAll(loadGatewayFilters(DEFAULT_FILTERS,
              new ArrayList<>(this.gatewayProperties.getDefaultFilters())));
  }
  // 如果routeDefinition里的过滤器不为空,加入过滤器
  if (!routeDefinition.getFilters().isEmpty()) {
      filters.addAll(loadGatewayFilters(routeDefinition.getId(),
              new ArrayList<>(routeDefinition.getFilters())));
  }
  // 排序
  AnnotationAwareOrderComparator.sort(filters);
  return filters;
}
List<GatewayFilter> loadGatewayFilters(String id,List<FilterDefinition> filterDefinitions) {
  ArrayList<GatewayFilter> ordered = new ArrayList<>(filterDefinitions.size());
  for (int i = 0; i < filterDefinitions.size(); i++) {
      // Filter定义 
      FilterDefinition definition = filterDefinitions.get(i);
      // 根据Filter定义的name获取GatewayFilterFactory
      GatewayFilterFactory factory = this.gatewayFilterFactories
              .get(definition.getName());
      // 配置
      Object configuration = this.configurationService.with(factory)
              .name(definition.getName())
              .properties(definition.getArgs())
              .eventFunction((bound, properties) -> new FilterArgsEvent(
                      RouteDefinitionRouteLocator.this, id, (Map<String, Object>) properties))
              .bind();
      // 转换为GatewayFilter
      GatewayFilter gatewayFilter = factory.apply(configuration);
      if (gatewayFilter instanceof Ordered) {
          ordered.add(gatewayFilter);
      }
      else {
          ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
      }
  }

  return ordered;
}
复制代码

总结

  • 理清Route、RouteLocator、RouteDefinition、RouteDefinitionLocator的含义。最后对运行时实际暴露的对象只有CachingRouteLocator和Route。
  • RouteRefreshListener接收容器事件,发布RefreshRoutesEvent事件,触发路由加载至CachingRouteLocator。

猜你喜欢

转载自blog.csdn.net/Java6888/article/details/109026082