【Spring Cloud】Gateway —— RouteLocator RouteDefinitionLocator FilteringWebHandler

前言

RouteLocator RouteDefinitionLocator FilteringWebHandler 及相关装配类的维度记录一下 Spring Cloud Gateway

RouteLocator

public interface RouteLocator {

	Flux<Route> getRoutes();

}

路由(Route)定位类,一般配置 Spring Cloud Gateway 我们也会基于 RouteLocatorBuilder 构造对应的 RouteLocator,诸如:

	@Bean
	public RouteLocator routeLocator(RouteLocatorBuilder builder) {

		return builder.routes()
				.route(p -> p
						.path("/client1/{segment}")
						.filters(f -> f.stripPrefix(1))
						.uri("http://localhost:8801/")
				)
				.build();
	}

当然,它是支持多组路由收集的:
RouteLocator

CachingRouteLocator

缓存内部的 RouteLocator 并基于事件刷新

CompositeRouteLocator

组合,将多组 RouteLocator 组合成一个

RouteDefinitionRouteLocator

	@Override
	public Flux<Route> getRoutes() {

		/**
		 * 基于 routeDefinitionLocator 获取所有 RouteDefinition
		 * 		转换成 Route 实例
		 */
		Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions().map(this::convertToRoute);

		// ...

		return routes.map(route -> {
			if (logger.isDebugEnabled()) {
				logger.debug("RouteDefinition matched: " + route.getId());
			}
			return route;
		});
	}
  • 基于 routeDefinitionLocator 获取所有 RouteDefinition 并转换成 Route 实例
  • 可以看到,真正负责路由解析的就只有此类,以及我们之前提到配置类中基于 RouteLocatorBuilder 构造的匿名实例

装配类 GatewayAutoConfiguration

	@Bean
	public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
			List<GatewayFilterFactory> gatewayFilters, List<RoutePredicateFactory> predicates,
			RouteDefinitionLocator routeDefinitionLocator, ConfigurationService configurationService) {
		return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, gatewayFilters, properties,
				configurationService);
	}

	@Bean
	@Primary
	@ConditionalOnMissingBean(name = "cachedCompositeRouteLocator")
	public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
		/**
		 * 组合所有 RouteLocator 实例并缓存
		 */
		return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
	}

自动装配类 GatewayAutoConfiguration 中:

  • 注册了 RouteDefinitionRouteLocator 实例
  • 收集容器中所有 RouteLocator 实例(实际上就是我们上面描述的两种),CompositeCaching,注册 CachingRouteLocator 实例
  • 因为 @Primary 注解,因此之后容器中主要使用的就是 cachedCompositeRouteLocator 这个实例了

RouteDefinitionLocator

public interface RouteDefinitionLocator {

	Flux<RouteDefinition> getRouteDefinitions();

}
  • 之前提到,RouteDefinitionRouteLocator 基于 routeDefinitionLocator 获取所有 RouteDefinition 并转换成 Route 实例
  • RouteDefinitionLocator,路由定义定位器,用于收集多组 RouteDefinition,最终交给 RouteDefinitionRouteLocator 转换成 Route

RouteDefiitionLocator

CachingRouteDefinitionLocator

缓存内部的 RouteDefinitionLocator 并基于事件刷新

CompositeRouteDefinitionLocator

它组合了一组 RouteDefinitionLocator,因而 getRouteDefinitions 方法是发射所有的 RouteDefinition 元素

InMemoryRouteDefinitionRepository

基于内存管理一组 RouteDefinition,提供了 save delete 方法,自动装配类中默认提供了实例,可以自行覆盖,如下:

	@Bean
	public RouteDefinitionRepository repository() {
		PredicateDefinition predicateDefinition = new PredicateDefinition("Path=/eureka-client/{segement}");

		FilterDefinition filterDefinition = new FilterDefinition("StripPrefix=1");

		RouteDefinition routeDefinition = new RouteDefinition();
		routeDefinition.setId("test-repo");
		routeDefinition.setPredicates(Arrays.asList(new PredicateDefinition[] { predicateDefinition }));
		routeDefinition.setFilters(Arrays.asList(new FilterDefinition[] { filterDefinition }));
		routeDefinition.setUri(URI.create("http://localhost:8801"));

		InMemoryRouteDefinitionRepository repository = new InMemoryRouteDefinitionRepository();

		Mono<RouteDefinition> route = Mono.fromSupplier(() -> routeDefinition);
		
		// 这里必须 subscribe 一下,暂不知原因 @TODO
		repository.save(route).subscribe();
		return repository;
	}

PropertiesRouteDefinitionLocator


	private final GatewayProperties properties;
	
	@Override
	public Flux<RouteDefinition> getRouteDefinitions() {
		return Flux.fromIterable(this.properties.getRoutes());
	}

基于 GatewayProperties 获取,实际上就是基于 配置文件 读取,类似:

spring:
  application:
    name: gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: test
          uri: http://localhost:8801
          predicates:
            - Path=/client/{segement}
          filters:
            - StripPrefix=1

DiscoveryClientRouteDefinitionLocator

这个类是基于 服务发现 来为每个服务生成默认的 RouteDefinition,基于 PathRoutePredicateFactory 匹配路由,基于 RewritePathGatewayFilterFactory 重写路径为 lb:// + serviceId

装配类

GatewayAutoConfiguration

	@Bean
	@ConditionalOnMissingBean
	public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
		return new PropertiesRouteDefinitionLocator(properties);
	}

	@Bean
	@ConditionalOnMissingBean(RouteDefinitionRepository.class)
	public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
		return new InMemoryRouteDefinitionRepository();
	}

	@Bean
	@Primary
	public RouteDefinitionLocator routeDefinitionLocator(List<RouteDefinitionLocator> routeDefinitionLocators) {
		return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators));
	}
  • 注册基于配置文件解析的 PropertiesRouteDefinitionLocator
  • 注册基于内存管理的 InMemoryRouteDefinitionRepository
  • CompositeRouteDefinitionLocator 管理上述所有 RouteDefinitionLocator,标注 @Primary,容器中可以直接注入使用

GatewayDiscoveryClientAutoConfiguration

	@Bean
	public DiscoveryLocatorProperties discoveryLocatorProperties() {
		DiscoveryLocatorProperties properties = new DiscoveryLocatorProperties();
		properties.setPredicates(initPredicates());
		properties.setFilters(initFilters());
		return properties;
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnProperty(value = "spring.cloud.discovery.reactive.enabled", matchIfMissing = true)
	public static class ReactiveDiscoveryClientRouteDefinitionLocatorConfiguration {

		@Bean
		@ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled")
		public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(
				ReactiveDiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {
			return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);
		}

	}
  • 配置服务发现默认的路由匹配器和过滤器,即之前提到的 PathRoutePredicateFactoryRewritePathGatewayFilterFactory
  • 注册 DiscoveryClientRouteDefinitionLocator 实例,基于配置项 spring.cloud.gateway.discovery.locator.enabled=true

FilteringWebHandler

	@Override
	public Mono<Void> handle(ServerWebExchange exchange) {
		Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);

		/**
		 * 从 route 实例中获取拦截器,此处包括 default-filters
		 */
		List<GatewayFilter> gatewayFilters = route.getFilters();

		/**
		 * 再加入 globalFilters
		 */
		List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
		combined.addAll(gatewayFilters);

		// 基于 Order 接口排序
		AnnotationAwareOrderComparator.sort(combined);

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

		// 拦截操作
		return new DefaultGatewayFilterChain(combined).filter(exchange);
	}
  • 此处会获取 Route 实例中的所有 Filter,包括 default-filters(配置文件指定,配置项 spring.cloud.gateway.default-filters
  • 还会加上所有容器中的 globalFilters,装配类中默认注册了不少,略
  • 最后进行拦截操作

装配类 GatewayAutoConfiguration

	@Bean
	public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
		return new FilteringWebHandler(globalFilters);
	}

总结

Spring Cloud Gateway 源码阅读的相关记录

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值