赞
踩
Spring-Cloud-Gateway路由信息是通过路由定位器RouteLocator加载以及初始化的接下来阅读源码看下Spring-Cloud-Gateway是怎么一步一步的实现了路由的加载初始化。
首选我们还是在Spring-Cloud-Gateway初始化配置中看Spring-Cloud-Gateway初始化是创建了路由定位相关的那些类
- ------------- GatewayAutoConfiguration类
- /**
- * 创建一个根据RouteDefinition转换的路由定位器
- */
- @Bean
- public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
- List<GatewayFilterFactory> GatewayFilters,
- List<RoutePredicateFactory> predicates,
- RouteDefinitionLocator routeDefinitionLocator) {
- return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties);
- }
-
- /**
- * 创建一个缓存路由的路由定位器
- * @param routeLocators
- * @return
- */
- @Bean
- @Primary//意思是在众多相同的bean中,优先使用用@Primary注解的bean.
- //TODO: property to disable composite?
- public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
-
- //1.创建组合路由定位器,根据(容器)已有的路由定位器集合
- //2.创建缓存功能的路由定位器
- return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
- }
从初始化配置类中可以路由定位器的创建流程
- RouteDefinitionRouteLocator
- CompositeRouteLocator
- CachingRouteLocator
- 其中 RouteDefinitionRouteLocator 是获取路由的主要地方,CompositeRouteLocator,CachingRouteLocator对路由定位器做了附加功能的包装,最终使用的是CachingRouteLocator对外提供服务
下来阅读RouteLocator 接口源码:
- /**
- * 路由定位器,服务获取路由信息
- * 1.可以通过 RouteDefinitionRouteLocator 获取 RouteDefinition ,并转换成 Route
- * @author Spencer Gibb
- */
- //TODO: rename to Routes?
- public interface RouteLocator {
-
- /**
- * 获取路由
- * @return
- */
- Flux<Route> getRoutes();
- }
接口很简单,有且只有一个获取路由的方法,专门用来获取路由。
RouteLocator 类图如下:
- graph TD
- RouteLocator-->|缓存功能实现|CachingRouteLocator
- RouteLocator-->|组合功能实现|CompositeRouteLocator
- RouteLocator-->|通过路由定义转换路由实现|RouteDefinitionRouteLocator
接下来我们依次阅读具体实现类
- /**
- * 路由定位器的包装类,实现了路由的本地缓存功能
- * @author Spencer Gibb
- */
- public class CachingRouteLocator implements RouteLocator {
-
- /**
- * 目标路由定位器
- */
- private final RouteLocator delegate;
-
- /**
- * 路由信息
- * Flux 相当于一个 RxJava Observable,
- * 能够发出 0~N 个数据项,然后(可选地)completing 或 erroring。处理多个数据项作为stream
- */
- private final Flux<Route> routes;
-
- /**
- * 本地缓存,用于缓存路由定位器获取的路由集合
- *
- */
- private final Map<String, List> cache = new HashMap<>();
- public CachingRouteLocator(RouteLocator delegate) {
- this.delegate = delegate;
- routes = CacheFlux.lookup(cache, "routes", Route.class)
- .onCacheMissResume(() -> this.delegate.getRoutes().sort(AnnotationAwareOrderComparator.INSTANCE));
- }
- @Override
- public Flux<Route> getRoutes() {
- return this.routes;
- }
-
- /**
- * Clears the routes cache
- * @return routes flux
- */
- public Flux<Route> refresh() {
- this.cache.clear();
- return this.routes;
- }
-
- @EventListener(RefreshRoutesEvent.class)
- /* for testing */ void handleRefresh() {
- refresh();
- }
- }
- 此类实现了对路由信息的本地缓存,通过Map<String, List> cache 缓存路由到内存中
- 此类通过@EventListener(RefreshRoutesEvent.class)监听RefreshRoutesEvent事件实现了对缓存的动态刷新。
备注:动态刷新可以在GatewayControllerEndpoint中通过http请求发布刷新事件
- @RestControllerEndpoint(id = "gateway")
- public class GatewayControllerEndpoint implements ApplicationEventPublisherAware{
- // 调用url= /gateway/refresh 刷新缓存中的路由信息
- @PostMapping("/refresh")
- public Mono<Void> refresh() {
- this.publisher.publishEvent(new RefreshRoutesEvent(this));
- return Mono.empty();
- }
- }
- /**
- *
- * 组合多个 RRouteLocator 的实现,为Route提供统一获取入口
- * @author Spencer Gibb
- */
- public class CompositeRouteLocator implements RouteLocator {
-
- /**
- * 能够发出 0~N 个数据项(RouteLocator),然后(可选地)completing 或 erroring。处理多个数据项作为stream
- */
- private final Flux<RouteLocator> delegates;
-
- public CompositeRouteLocator(Flux<RouteLocator> delegates) {
- this.delegates = delegates;
- }
-
- @Override
- public Flux<Route> getRoutes() {
- //this.delegates.flatMap((routeLocator)-> routeLocator.getRoutes());
- return this.delegates.flatMap(RouteLocator::getRoutes);
- }
- }
- 此类将遍历传入的目录路由定位器集合,组合每个路由定位器获取到的路由信息
- /**
- * 路由定位器
- * 此实现通过路由定义(RouteDefinition)转换路由(Route)
- * {@link RouteLocator} that loads routes from a {@link RouteDefinitionLocator}
- * @author Spencer Gibb
- */
- public class RouteDefinitionRouteLocator implements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware {
-
- public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator,
- List<RoutePredicateFactory> predicates,
- List<GatewayFilterFactory> gatewayFilterFactories,
- GatewayProperties gatewayProperties) {
- this.routeDefinitionLocator = routeDefinitionLocator;
- initFactories(predicates);
- gatewayFilterFactories.forEach(factory -> this.gatewayFilterFactories.put(factory.name(), factory));
- this.gatewayProperties = gatewayProperties;
- }
-
- @Override
- public Flux<Route> getRoutes() {
- //获取到所有的RouteDefinition
- return this.routeDefinitionLocator.getRouteDefinitions()
- //遍历转换成对应的Route信息
- .map(this::convertToRoute)
- //TODO: error handling
- .map(route -> {
- if (logger.isDebugEnabled()) {
- logger.debug("RouteDefinition matched: " + route.getId());
- }
- return route;
- });
-
-
- /* TODO: trace logging
- if (logger.isTraceEnabled()) {
- logger.trace("RouteDefinition did not match: " + routeDefinition.getId());
- }*/
- }
- }
- 此类的核心方法getRoutes通过传入的routeDefinitionLocator获取路由定位,并循环遍历路由定位依次转换成路由返回,
- 代码中可以看到getRoutes通过convertToRoute方法将路由定位转换成路由的
- /**
- * RouteDefinition 转换为对应的Route
- * @param routeDefinition
- * @return
- */
- private Route convertToRoute(RouteDefinition routeDefinition) {
- //获取routeDefinition中的Predicate信息
- Predicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
- //获取routeDefinition中的GatewayFilter信息
- List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);
- //构建路由信息
- return Route.builder(routeDefinition)
- .predicate(predicate)
- .replaceFilters(gatewayFilters)
- .build();
- }
- convertToRoute方法功能作用
- 获取routeDefinition中的Predicate信息 (通过combinePredicates方法)
- 获取routeDefinition中的GatewayFilter信息(通过gatewayFilters方法)
- 构建路由信息
- /**
- * 返回组合的谓词
- * @param routeDefinition
- * @return
- */
- private Predicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {
- //获取RouteDefinition中的PredicateDefinition集合
- List<PredicateDefinition> predicates = routeDefinition.getPredicates();
-
- Predicate<ServerWebExchange> predicate = lookup(routeDefinition, predicates.get(0));
-
- for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) {
- Predicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
- //流程4
- //返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑AND
- predicate = predicate.and(found);
- }
-
- return predicate;
- }
-
- /**
- * 获取一个谓语定义(PredicateDefinition)转换的谓语
- * @param route
- * @param predicate
- * @return
- */
- @SuppressWarnings("unchecked")
- private Predicate<ServerWebExchange> lookup(RouteDefinition route, PredicateDefinition predicate) {
- //流程1
- //流程1==获取谓语创建工厂
- RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName());
- if (factory == null) {
- throw new IllegalArgumentException("Unable to find RoutePredicateFactory with name " + predicate.getName());
- }
- //流程2
- //获取参数
- Map<String, String> args = predicate.getArgs();
- if (logger.isDebugEnabled()) {
- logger.debug("RouteDefinition " + route.getId() + " applying "
- + args + " to " + predicate.getName());
- }
-
- //组装参数
- Map<String, Object> properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory);
- //构建创建谓语的配置信息
- Object config = factory.newConfig();
- ConfigurationUtils.bind(config, properties,
- factory.shortcutFieldPrefix(), predicate.getName(), validator);
- if (this.publisher != null) {
- this.publisher.publishEvent(new PredicateArgsEvent(this, route.getId(), properties));
- }
- //流程3
- //通过谓语工厂构建谓语
- return factory.apply(config);
- }
PredicateDefinition 谓语定义以及在前面文中阅读过源码了
获取Predicate流程如下
- 根据PredicateDefinition name 获取 RoutePredicateFactory
- 根据PredicateDefinition args 组装 config信息
- 通过RoutePredicateFactory 根据config信息创建Predicate信息
- 多个Predicate 以短路逻辑AND组合
- private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {
- List<GatewayFilter> filters = new ArrayList<>();
-
- //校验gatewayProperties是否含义默认的过滤器集合
- //TODO: support option to apply defaults after route specific filters?
- if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
- //加载全局配置的默认过滤器集合
- filters.addAll(loadGatewayFilters("defaultFilters",
- this.gatewayProperties.getDefaultFilters()));
- }
-
- if (!routeDefinition.getFilters().isEmpty()) {
- //加载路由定义中的过滤器集合
- filters.addAll(loadGatewayFilters(routeDefinition.getId(), routeDefinition.getFilters()));
- }
-
- //排序
- AnnotationAwareOrderComparator.sort(filters);
- return filters;
- }
- /**
- * 加载过滤器,根据过滤器的定义加载
- * @param id
- * @param filterDefinitions
- * @return
- */
- @SuppressWarnings("unchecked")
- private List<GatewayFilter> loadGatewayFilters(String id, List<FilterDefinition> filterDefinitions) {
- //遍历过滤器定义,将过滤器定义转换成对应的过滤器
- List<GatewayFilter> filters = filterDefinitions.stream()
- .map(definition -> {
-
- //流程1 //通过过滤器定义名称获取过滤器创建工厂
- GatewayFilterFactory factory = this.gatewayFilterFactories.get(definition.getName());
- if (factory == null) {
- throw new IllegalArgumentException("Unable to find GatewayFilterFactory with name " + definition.getName());
- }
- //流程2
- //获取参数
- Map<String, String> args = definition.getArgs();
- if (logger.isDebugEnabled()) {
- logger.debug("RouteDefinition " + id + " applying filter " + args + " to " + definition.getName());
- }
-
- //根据args组装配置信息
- Map<String, Object> properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory);
- //构建过滤器创建配置信息
- Object configuration = factory.newConfig();
- ConfigurationUtils.bind(configuration, properties,
- factory.shortcutFieldPrefix(), definition.getName(), validator);
-
- //流程3
- //通过过滤器工厂创建GatewayFilter
- GatewayFilter gatewayFilter = factory.apply(configuration);
- if (this.publisher != null) {
- //发布事件
- this.publisher.publishEvent(new FilterArgsEvent(this, id, properties));
- }
- return gatewayFilter;
- })
- .collect(Collectors.toList());
-
- ArrayList<GatewayFilter> ordered = new ArrayList<>(filters.size());
- //包装过滤器使其所有过滤器继承Ordered属性,可进行排序
- for (int i = 0; i < filters.size(); i++) {
- GatewayFilter gatewayFilter = filters.get(i);
- if (gatewayFilter instanceof Ordered) {
- ordered.add(gatewayFilter);
- }
- else {
- ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
- }
- }
-
- return ordered;
- }
- getFilters 方法 同时加载 全局配置 gatewayProperties与routeDefinition配置下的所有过滤器定义filterDefinitions
- loadGatewayFilters 负责将filterDefinition转化成对应的GatewayFilter
转化流程如下
- 根据filterDefinition name 获取 GatewayFilterFactory
- 根据filterDefinition args 组装 config信息
- 通过GatewayFilterFactory 根据config信息创建PGatewayFilter信息
至此,阅读了路由的数据模型,路由定义加载,路由的加载(路由定义转化为路由),Spring-Cloud-Gateway路由的创建加载流程已经清晰明了的展现出来,在使用中也可以快速的对其扩展,以及根据实际需求进行个性化的定制操作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。