返回

05.route路由的配置加载

05.route路由的配置加载

route路由的配置加载


主要在sprng-cloud-gateway-server的route包定义路由相关的定义,构建和加载

![路由](https://fengzhenbing.github.io/img/picgo/image (2).png)

0.相关配置

  • 通过springboot spi方式,springboot会启动spring.factories中配置的 org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 
org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\
org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration,\
  ...

1.路由定义

  • 路由定义RouteDefinition
public class RouteDefinition {

   private String id;

   @NotEmpty
   @Valid//fzb 断言定义数组
   private List<PredicateDefinition> predicates = new ArrayList<>();

   @Valid//fzb 过滤器定义数组
   private List<FilterDefinition> filters = new ArrayList<>();

   @NotNull//fzb 路由路径
   private URI uri;
   ...
   }
  • 路由定义定位器

获取路由的定义,负责读取上述路由定义配置 RouteDefinition,最终会通过路由定义生成路由

public interface RouteDefinitionLocator {
   //fzb 获取路由定义对象
   Flux<RouteDefinition> getRouteDefinitions();
}

有以下实现:

![image (3)](https://fengzhenbing.github.io/img/picgo/image (3).png)

  • CachingRouteDefinitionLocator: 它包装了CompositeRouteDefinitionLocator,缓存路由定义RouteDefinition列表

public class CachingRouteDefinitionLocator implements RouteDefinitionLocator, ApplicationListener {//fzb 事件监听RefreshRoutesEvent

private static final String CACHE_KEY = "routeDefs";

private final RouteDefinitionLocator delegate;
//fzb 路由定义flux
private final Flux<RouteDefinition> routeDefinitions;
//fzb 内存缓存RouteDefinition
private final Map<String, List> cache = new ConcurrentHashMap<>();
...

//fzb 监听到路由刷新事件,重新获取路由并缓存到cache
@Override
public void onApplicationEvent(RefreshRoutesEvent event) {
	fetch().materialize().collect(Collectors.toList())
            .doOnNext(routes -> cache.put(CACHE_KEY, routes)).subscribe();
}

… }

 > * CompositeRouteDefinitionLocator:
> 遍历执行所有RouteDefinitionLocator的查找路由定义方法,将找到的路由定义合并; 组合多种 RouteDefinitionLocator 的实现,为 routeDefinitions提供统一入口
​```java
public class CompositeRouteDefinitionLocator implements RouteDefinitionLocator {
...
	//fzb 组合多个路由定义定位器RouteDefinitionLocator
	private final Flux<RouteDefinitionLocator> delegates;
	// fzb 路由定义的id 生成器,默认UUID
	private final IdGenerator idGenerator;
...
	public CompositeRouteDefinitionLocator(Flux<RouteDefinitionLocator> delegates,
			IdGenerator idGenerator) {
		this.delegates = delegates;
		this.idGenerator = idGenerator;// 路由定义的id 生成器,默认UUID
	}

	@Override
	public Flux<RouteDefinition> getRouteDefinitions() {
      //遍历执行所有RouteDefinitionLocator的查找路由定义方法,将找到的路由定义合并
		return this.delegates
				.flatMapSequential(RouteDefinitionLocator::getRouteDefinitions)
				.flatMap(routeDefinition -> {
					if (routeDefinition.getId() == null) {
						return randomId().map(id -> {
							routeDefinition.setId(id);// 设置uuid
							if (log.isDebugEnabled()) {
								log.debug(
										"Id set on route definition: " + routeDefinition);
							}
							return routeDefinition;
						});
					}
					return Mono.just(routeDefinition);
				});
	}
 ...
}
  • PropertiesRouteDefinitionLocator: 从配置文件(GatewayProperties 例如,YML / Properties 等 ) 读取RouteDefinition
   //fzb 从GatewayProperties读取路由定义
   @Override
   public Flux<RouteDefinition> getRouteDefinitions() {
       return Flux.fromIterable(this.properties.getRoutes());
   }
  • DiscoveryClientRouteDefinitionLocator 从注册中心如:Netflix Eureka, Consul 或 Zookeeper读取RouteDefinition
public DiscoveryClientRouteDefinitionLocator(ReactiveDiscoveryClient discoveryClient,
      DiscoveryLocatorProperties properties) {
   this(discoveryClient.getClass().getSimpleName(), properties);
   //fzb 通过服务发现客户端 ,比如eureka客户端从注册中心拿到所有的服务实例
   serviceInstances = discoveryClient.getServices()
         .flatMap(service -> discoveryClient.getInstances(service).collectList());
}

将服务实例serviceInstances转为路由定义

@Override
public Flux<RouteDefinition> getRouteDefinitions() {
  SpelExpressionParser parser = new SpelExpressionParser();
  Expression includeExpr = parser
        .parseExpression(properties.getIncludeExpression());//fzb  扩展点,可以通过properties 配置其他spel
  Expression urlExpr = parser.parseExpression(properties.getUrlExpression());
  ...
}
  • RouteDefinitionRepository 从存储器(内存 / Redis / MySQL 等 )读取RouteDefinition,实现RouteDefinitionWriter接口; 提供删除和保存RouteDefinition的方法; 默认实现有:InMemoryRouteDefinitionRepository,没有RouteDefinitionRepository的实例,则默认用InMemoryRouteDefinitionRepository
public class InMemoryRouteDefinitionRepository implements RouteDefinitionRepository {

	private final Map<String, RouteDefinition> routes = synchronizedMap(
			new LinkedHashMap<String, RouteDefinition>());//fzb 内存中用 同步map 存储

	@Override// fzb 保存路由到内存中
	public Mono<Void> save(Mono<RouteDefinition> route) {
		return route.flatMap(r -> {
			if (StringUtils.isEmpty(r.getId())) {
				return Mono.error(new IllegalArgumentException("id may not be empty"));
			}
			routes.put(r.getId(), r);//保存
			return Mono.empty();
		});
	}

	@Override// fzb 从内存中删除路由
	public Mono<Void> delete(Mono<String> routeId) {
		...
	}

	@Override// fzb 获取路由定义
	public Flux<RouteDefinition> getRouteDefinitions() {
		return Flux.fromIterable(routes.values());
	}

}

2.路由

  • 路由Route
public class Route implements Ordered {

   private final String id;
   //fzb 路由地址
   private final URI uri;
   //fzb 路由的优先级
   private final int order;

   private final AsyncPredicate<ServerWebExchange> predicate;
   //fzb gatewayFilter列表
   private final List<GatewayFilter> gatewayFilters;
   //fzb 元数据
   private final Map<String, Object> metadata;
...
}
  • 路由定位器 RouteLocator 获取路由对象
public interface RouteLocator {
	//fzb 获取路由对象
	Flux<Route> getRoutes();

}

routeLocator

类似RouteDefinitionLocator三个实现:

  • 缓存:CachingRouteLocator: 缓存路由,查找时使用CompositeRouteLocator去查找
  • 组合: CompositeRouteLocator:使用多个RouteLocator查找路由并合并
  • 单个的 RouteDefinitionRouteLocator:最终使用RouteDefinitionLocator查找路由定义并转为路由对象Route 单个路由的 filters = GlobalFilter + 默认GatewayFilter + 本路由配置的GatewayFilter
public class RouteDefinitionRouteLocator
		implements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware {

	 ...
 
	public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator,
			List<RoutePredicateFactory> predicates,
			List<GatewayFilterFactory> gatewayFilterFactories,
			GatewayProperties gatewayProperties,
			ConfigurationService configurationService) {
		this.routeDefinitionLocator = routeDefinitionLocator;//fzb //设置路由定义定位器
		this.configurationService = configurationService;
		initFactories(predicates);//fzb //初始化路由断言工厂
		gatewayFilterFactories.forEach(
				factory -> this.gatewayFilterFactories.put(factory.name(), factory));//fzb //初始化网关过滤器
		this.gatewayProperties = gatewayProperties;
	}
...
 
   //fzb  获取路由对象: 先获取RouteDefinition,再转为 Route
	@Override
	public Flux<Route> getRoutes() {
		Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions()
				.map(this::convertToRoute);//fzb RouteDefinition转为 Route
        ...
	}
	//fzb 路由定义转为 路由
	private Route convertToRoute(RouteDefinition routeDefinition) {
        //fzb 1,将本路由定义中各个断言 与运算 合并为一个 AsyncPredicate
		AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
        //fzb 2, 获取所有的默认的过滤器和本路由定义的过滤器
		List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);
        // 组装Route
		return Route.async(routeDefinition).asyncPredicate(predicate)
				.replaceFilters(gatewayFilters).build();
	}
	//fzb  过滤器定义filterDefinitions加载为过滤器GatewayFilter
	@SuppressWarnings("unchecked")
	List<GatewayFilter> loadGatewayFilters(String id,
			List<FilterDefinition> filterDefinitions) {
		ArrayList<GatewayFilter> ordered = new ArrayList<>(filterDefinitions.size());
		for (int i = 0; i < filterDefinitions.size(); i++) {
			FilterDefinition definition = filterDefinitions.get(i);
			GatewayFilterFactory factory = this.gatewayFilterFactories
					.get(definition.getName());
			if (factory == null) {
				throw new IllegalArgumentException(
						"Unable to find GatewayFilterFactory with name "
								+ definition.getName());
			}
			if (logger.isDebugEnabled()) {
				logger.debug("RouteDefinition " + id + " applying filter "
						+ definition.getArgs() + " to " + definition.getName());
			}

			// @formatter:off
			Object configuration = this.configurationService.with(factory)
					.name(definition.getName())
					.properties(definition.getArgs())
					.eventFunction((bound, properties) -> new FilterArgsEvent(
							// TODO: why explicit cast needed or java compile fails
							RouteDefinitionRouteLocator.this, id, (Map<String, Object>) properties))
					.bind();
			// @formatter:on

			// some filters require routeId
			// TODO: is there a better place to apply this?
			if (configuration instanceof HasRouteId) {
				HasRouteId hasRouteId = (HasRouteId) configuration;
				hasRouteId.setRouteId(id);
			}

			GatewayFilter gatewayFilter = factory.apply(configuration);
			if (gatewayFilter instanceof Ordered) {
				ordered.add(gatewayFilter);
			}
			else {
				ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
			}
		}

		return ordered;
	}

	private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {
		List<GatewayFilter> filters = new ArrayList<>();
		//fzb 1,加上默认的过滤器
		// TODO: support option to apply defaults after route specific filters?
		if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
			filters.addAll(loadGatewayFilters(DEFAULT_FILTERS,
					new ArrayList<>(this.gatewayProperties.getDefaultFilters())));
		}
		//fzb 2,加上本路由配置的过滤器
		if (!routeDefinition.getFilters().isEmpty()) {
			filters.addAll(loadGatewayFilters(routeDefinition.getId(),
					new ArrayList<>(routeDefinition.getFilters())));
		}
		//fzb 排序 按实现的Ordered接口
		AnnotationAwareOrderComparator.sort(filters);
		return filters;
	}
	//fzb combinePredicates主要是对找出来的predicate进行and操作
	private AsyncPredicate<ServerWebExchange> combinePredicates(
			RouteDefinition routeDefinition) {
		List<PredicateDefinition> predicates = routeDefinition.getPredicates();
		if (predicates == null || predicates.isEmpty()) {
			// this is a very rare case, but possible, just match all
			return AsyncPredicate.from(exchange -> true);
		}
		AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition,
				predicates.get(0));

		for (PredicateDefinition andPredicate : predicates.subList(1,
				predicates.size())) {
			AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition,
					andPredicate);
			predicate = predicate.and(found);//fzb and 各个断言 	与 合并为一个 AsyncPredicate
		}

		return predicate;
	}

	 ...

}

类比

  • Route -> RouteDefinition ->RouteDefinitionLocator -> xxxRouteDefinitionRepository
  • Bean -> BeanDefinition -> BeanDefinitionRegistry -> DefaultListableBeanFactory#Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
Built with Hugo
Theme Stack designed by Jimmy
本站访问量:   您是本站第 位访问者