一、核心概念
路由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。