博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊spring cloud gateway的RouteLocator
阅读量:6163 次
发布时间:2019-06-21

本文共 9846 字,大约阅读时间需要 32 分钟。

本文主要研究一下spring cloud gateway的RouteLocator

RouteLocator

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/route/RouteLocator.java

public interface RouteLocator {	Flux
getRoutes();}复制代码

其有三个实现类:

  • RouteDefinitionRouteLocator
  • CompositeRouteLocator
  • CachingRouteLocator

GatewayAutoConfiguration

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java

@Configuration@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)@EnableConfigurationProperties@AutoConfigureBefore(HttpHandlerAutoConfiguration.class)@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})@ConditionalOnClass(DispatcherHandler.class)public class GatewayAutoConfiguration {	//......	@Bean	public RouteLocatorBuilder routeLocatorBuilder(ConfigurableApplicationContext context) {		return new RouteLocatorBuilder(context);	}	@Bean	public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,												   List
GatewayFilters, List
predicates, RouteDefinitionLocator routeDefinitionLocator) { return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties); } @Bean @Primary //TODO: property to disable composite? public RouteLocator cachedCompositeRouteLocator(List
routeLocators) { return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators))); } @Bean public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator) { return new RoutePredicateHandlerMapping(webHandler, routeLocator); } @Configuration @ConditionalOnClass(Health.class) protected static class GatewayActuatorConfiguration { @Bean @ConditionalOnEnabledEndpoint public GatewayControllerEndpoint gatewayControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator, List
globalFilters, List
GatewayFilters, RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) { return new GatewayControllerEndpoint(routeDefinitionLocator, globalFilters, GatewayFilters, routeDefinitionWriter, routeLocator); } } //......}复制代码

可以看到默认创建了RouteDefinitionRouteLocator,然后又基于它创建了CompositeRouteLocator,最后由CachingRouteLocator再包装一层

RouteDefinitionRouteLocator

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java

/** * {@link RouteLocator} that loads routes from a {@link RouteDefinitionLocator} * @author Spencer Gibb */public class RouteDefinitionRouteLocator implements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware {	protected final Log logger = LogFactory.getLog(getClass());	private final RouteDefinitionLocator routeDefinitionLocator;	private final Map
predicates = new LinkedHashMap<>(); private final Map
gatewayFilterFactories = new HashMap<>(); private final GatewayProperties gatewayProperties; private final SpelExpressionParser parser = new SpelExpressionParser(); private BeanFactory beanFactory; private ApplicationEventPublisher publisher; public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator, List
predicates, List
gatewayFilterFactories, GatewayProperties gatewayProperties) { this.routeDefinitionLocator = routeDefinitionLocator; initFactories(predicates); gatewayFilterFactories.forEach(factory -> this.gatewayFilterFactories.put(factory.name(), factory)); this.gatewayProperties = gatewayProperties; } @Autowired private Validator validator; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } @Override public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { this.publisher = publisher; } private void initFactories(List
predicates) { predicates.forEach(factory -> { String key = factory.name(); if (this.predicates.containsKey(key)) { this.logger.warn("A RoutePredicateFactory named "+ key + " already exists, class: " + this.predicates.get(key) + ". It will be overwritten."); } this.predicates.put(key, factory); if (logger.isInfoEnabled()) { logger.info("Loaded RoutePredicateFactory [" + key + "]"); } }); } @Override public Flux
getRoutes() { return this.routeDefinitionLocator.getRouteDefinitions() .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()); }*/ } //......}复制代码
  • 这个类名有点绕,如同注释里头说的,它是一个routeLocator,从routeDefinitionLocator获取Route信息
  • 这里注入的routeDefinitionLocator是CompositeRouteDefinitionLocator,它组合了InMemoryRouteDefinitionRepository、PropertiesRouteDefinitionLocator、DiscoveryClientRouteDefinitionLocator三个RouteDefinitionLocator。
  • PropertiesRouteDefinitionLocator是直接使用GatewayProperties的getRoutes()获取,其是通过spring.cloud.gateway.routes配置得来。

convertToRoute

private Route convertToRoute(RouteDefinition routeDefinition) {		Predicate
predicate = combinePredicates(routeDefinition); List
gatewayFilters = getFilters(routeDefinition); return Route.builder(routeDefinition) .predicate(predicate) .replaceFilters(gatewayFilters) .build(); }复制代码

RouteDefinitionRouteLocator的getRoutes方法,从routeDefinitionLocator.getRouteDefinitions(),然后使用convertToRoute方法进行转换,该方法主要用到了combinePredicates、getFilters两个方法

combinePredicates

private Predicate
combinePredicates(RouteDefinition routeDefinition) { List
predicates = routeDefinition.getPredicates(); Predicate
predicate = lookup(routeDefinition, predicates.get(0)); for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) { Predicate
found = lookup(routeDefinition, andPredicate); predicate = predicate.and(found); } return predicate; } private Predicate
lookup(RouteDefinition route, PredicateDefinition predicate) { RoutePredicateFactory
factory = this.predicates.get(predicate.getName()); if (factory == null) { throw new IllegalArgumentException("Unable to find RoutePredicateFactory with name " + predicate.getName()); } Map
args = predicate.getArgs(); if (logger.isDebugEnabled()) { logger.debug("RouteDefinition " + route.getId() + " applying " + args + " to " + predicate.getName()); } Map
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)); } return factory.apply(config); }复制代码

这里利用工厂方法,根据config去apply出来Predicate 而combinePredicates主要是对找出来的predicate进行and操作

getFilters

private List
getFilters(RouteDefinition routeDefinition) { List
filters = new ArrayList<>(); //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; } private List
loadGatewayFilters(String id, List
filterDefinitions) { List
filters = filterDefinitions.stream() .map(definition -> { GatewayFilterFactory factory = this.gatewayFilterFactories.get(definition.getName()); if (factory == null) { throw new IllegalArgumentException("Unable to find GatewayFilterFactory with name " + definition.getName()); } Map
args = definition.getArgs(); if (logger.isDebugEnabled()) { logger.debug("RouteDefinition " + id + " applying filter " + args + " to " + definition.getName()); } Map
properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory); Object configuration = factory.newConfig(); ConfigurationUtils.bind(configuration, properties, factory.shortcutFieldPrefix(), definition.getName(), validator); GatewayFilter gatewayFilter = factory.apply(configuration); if (this.publisher != null) { this.publisher.publishEvent(new FilterArgsEvent(this, id, properties)); } return gatewayFilter; }) .collect(Collectors.toList()); ArrayList
ordered = new ArrayList<>(filters.size()); 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主要是利用loadGatewayFilters获取filter,返回使用AnnotationAwareOrderComparator进行排序 loadGatewayFilters也是利用工厂方法,使用GatewayFilterFactory根据config去apply出来具体的GatewayFilter实例

小结

RouteLocator接口用于获取路由信息,其有三个实现类

  • RouteDefinitionRouteLocator
  • CompositeRouteLocator
  • CachingRouteLocator

最终使用的是CachingRouteLocator,它包装了CompositeRouteLocator,而CompositeRouteLocator则组合了RouteDefinitionRouteLocator。

RouteDefinitionRouteLocator与RouteDefinitionLocator比较容易混淆,前者是一个RouteLocator,后者是一个RouteDefinitionLocator,前者的RouteDefinitionRouteLocator主要从后者获取路由定义信息。

doc

转载地址:http://ieefa.baihongyu.com/

你可能感兴趣的文章
Android Fragment应用实战
查看>>
SQL Server查询死锁并KILL
查看>>
内存或磁盘空间不足,Microsoft Office Excel 无法再次打开或保存任何文档。 [问题点数:20分,结帖人wenyang2004]...
查看>>
委托到Lambda的进化: ()=> {} 这个lambda表达式就是一个无参数的委托及具体方法的组合体。...
查看>>
apache 伪静态 .htaccess
查看>>
unity3d 截屏
查看>>
ASP.NET MVC学习之控制器篇
查看>>
MongoDB ServerStatus返回信息
查看>>
分析jQuery源码时记录的一点感悟
查看>>
程序局部性原理感悟
查看>>
UIView 动画进阶
查看>>
Spring如何处理线程并发
查看>>
linux常用命令(用户篇)
查看>>
获取组件的方式(方法)
查看>>
win2008 server_R2 自动关机 解决
查看>>
我的友情链接
查看>>
在C#调用C++的DLL简析(二)—— 生成托管dll
查看>>
Linux macos 常用终端操作
查看>>
企业网络的管理思路
查看>>
Linux磁盘分区与挂载
查看>>