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

2,078 阅读5分钟

一、核心概念

路由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装配,到加载RouteCachingRouteLocator

自动配置

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转换PredicateDefinitionAsyncPredicate

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#getFiltersFilterDefinition转换为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。