目录

基本组件

路由定位器(RouteDefinitionLocator )

路由定义(RouteDefinition)

PredicateDefinition

FilterDefinition

CompositeRouteDefinitionLocator

路由定位器 (RouteLocator)

Route

RouteDefinitionLocator解析

PropertiesRouteDefinitionLocator

GatewayProperties

RouteDefinitionRepository

RouteDefinitionWriter

InMemoryRouteDefinitionRepository

自定义RouteDefinitionRepository

DiscoveryClientRouteDefinitionLocator

RouteLocator解析

RouteLocator

CompositeRouteLocator

CachingRouteLocator

RouteDefinitionRouteLocator

构造函数

获得 Route

自定义 RouteLocator


基本组件

路由定位器(RouteDefinitionLocator )

RouteDefinitionLocator 负责读取路由配置(RouteDefinition ),Gateway实现了多种Locator。

public interface RouteDefinitionLocator {Flux<RouteDefinition> getRouteDefinitions();
}

  • PropertiesRouteDefinitionLocator

从配置文件( 例如,YML / Properties 等 ) 读取

  • RouteDefinitionRepository

从存储器( 例如,内存 / Redis / MySQL 等 )读取。

  • DiscoveryClientRouteDefinitionLocator

从注册中心( 例如,Eureka / Consul / Zookeeper / Etcd 等 )读取。

  • CompositeRouteDefinitionLocator

组合多种 RouteDefinitionLocator 的实现,为 RouteDefinitionRouteLocator 提供统一入口。

  • CachingRouteDefinitionLocator

已经被 CachingRouteLocator 取代。

路由定义(RouteDefinition)

@Validated
public class RouteDefinition {@NotEmptyprivate String id = UUID.randomUUID().toString();@NotEmpty@Validprivate List<PredicateDefinition> predicates = new ArrayList<>();@Validprivate List<FilterDefinition> filters = new ArrayList<>();@NotNullprivate URI uri;private int order = 0;
}
  • id 属性,ID 编号,唯一
  • predicates 属性,谓语定义数组。请求通过 predicates 判断是否匹配。在 Route 里,PredicateDefinition 转换成 Predicate 。
  • filters 属性,过滤器定义数组。在 Route 里,FilterDefinition 转换成 GatewayFilter 。
  • uri 属性,路由向的 URI 。
  • order 属性,顺序。当请求匹配到多个路由时,使用顺序的。

RouteDefinition 提供 text 字符串创建对象(yaml配置中属性值),格式为:

${id}=${uri},${predicates[0]},${predicates[1]}...${predicates[n]}

public RouteDefinition(String text) ;

PredicateDefinition

@Validated
public class PredicateDefinition {/*** 谓语定义名字,通过 name 对应到 org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory 的实现类*/@NotNullprivate String name;/*** 参数数组*/private Map<String, String> args = new LinkedHashMap<>();
}

提供了构造函数:

/*** 根据 text 创建 PredicateDefinition** @param text 格式 ${name}=${args[0]},${args[1]}...${args[n]}*             例如 Host=iocoder.cn*/
public PredicateDefinition(String text);

FilterDefinition

@Validated
public class FilterDefinition {/*** 过滤器定义名字。通过 name 对应到 org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory 的实现类*/@NotNullprivate String name;/*** 参数数组*/private Map<String, String> args = new LinkedHashMap<>();
}

提供了构造函数:

/*** 根据 text 创建 FilterDefinition** @param text 格式 ${name}=${args[0]},${args[1]}...${args[n]}*             例如 AddRequestParameter=foo, bar*/
public FilterDefinition(String text);

CompositeRouteDefinitionLocator

组合多种 RouteDefinitionLocator 的实现,为 RouteDefinitionRouteLocator 提供统一入口

 @Overridepublic Flux<RouteDefinition> getRouteDefinitions() {return this.delegates.flatMap(RouteDefinitionLocator::getRouteDefinitions).flatMap(routeDefinition -> {if (routeDefinition.getId() == null) {return randomId().map(id -> {routeDefinition.setId(id);if (log.isDebugEnabled()) {log.debug("Id set on route definition: " + routeDefinition);}return routeDefinition;});}return Mono.just(routeDefinition);});}

路由定位器 (RouteLocator)

  • RouteLocator 可以直接自定义路由( org.springframework.cloud.gateway.route.Route ) ,也可以通过 RouteDefinitionRouteLocator 获取 RouteDefinition ,并转换成 Route 。
  • RoutePredicateHandlerMapping 使用 RouteLocator 获得 Route 信息。

Route

Route与RouteDefinition结构相似。同时实现了Order接口。

public class Route implements Ordered {/*** 路由编号*/private final String id;/*** 路由向的 URI*/private final URI uri;/*** 顺序*/private final int order;/*** 谓语数组*/private final Predicate<ServerWebExchange> predicate;/*** 过滤器数组*/private final List<GatewayFilter> gatewayFilters;
}

Route 内置 Builder 类,根据RouteDefinition 构造对象。predicate / gatewayFilters 属性,需要调用 Builder 相关方法进行设置

 public static Builder builder(RouteDefinition routeDefinition) {// @formatter:offreturn new Builder().id(routeDefinition.getId()).uri(routeDefinition.getUri()).order(routeDefinition.getOrder()).metadata(routeDefinition.getMetadata());// @formatter:on}

RouteDefinitionLocator解析

PropertiesRouteDefinitionLocator

GatewayProperties 中获取路由信息。

public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator {private final GatewayProperties properties;public PropertiesRouteDefinitionLocator(GatewayProperties properties) {this.properties = properties;}@Overridepublic Flux<RouteDefinition> getRouteDefinitions() {return Flux.fromIterable(this.properties.getRoutes());}}

GatewayProperties

GatewayProperties ,从配置文件读取 :

  • 路由配置

通过 spring.cloud.gateway.routes 配置

  • 默认过滤器配置。当 RouteDefinition => Route 时,会将过滤器配置添加到每个 Route 。

通过 spring.cloud.gateway.default-filters 配置

@ConfigurationProperties("spring.cloud.gateway")
@Validated
public class GatewayProperties {/*** List of Routes.*/@NotNull@Validprivate List<RouteDefinition> routes = new ArrayList<>();/*** List of filter definitions that are applied to every route.*/private List<FilterDefinition> defaultFilters = new ArrayList<>();
}

RouteDefinitionRepository

public interface RouteDefinitionRepositoryextends RouteDefinitionLocator, RouteDefinitionWriter {}

类继承关系如下:

RouteDefinitionWriter

RouteDefinitionWriter ,路由配置写入接口。该接口定义了保存删除两个方法

public interface RouteDefinitionWriter {/*** 保存路由配置** @param route 路由配置* @return Mono<Void>*/Mono<Void> save(Mono<RouteDefinition> route);/*** 删除路由配置** @param routeId 路由编号* @return Mono<Void>*/Mono<Void> delete(Mono<String> routeId);
}

InMemoryRouteDefinitionRepository

基于内存为存储器的 RouteDefinitionLocator

public class InMemoryRouteDefinitionRepository implements RouteDefinitionRepository {private final Map<String, RouteDefinition> routes = synchronizedMap(new LinkedHashMap<String, RouteDefinition>());@Overridepublic Flux<RouteDefinition> getRouteDefinitions() {return Flux.fromIterable(routes.values());}
}

路由信息构造:

@Overridepublic 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();});}@Overridepublic Mono<Void> delete(Mono<String> routeId) {return routeId.flatMap(id -> {if (routes.containsKey(id)) {routes.remove(id);return Mono.empty();}return Mono.defer(() -> Mono.error(new NotFoundException("RouteDefinition not found: " + routeId)));});}

自定义RouteDefinitionRepository

可以自定义RouteDefinitionRepository,如果没有自定义,才使用内存存储。

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

DiscoveryClientRouteDefinitionLocator

DiscoveryClientRouteDefinitionLocator 通过调用 org.springframework.cloud.client.discovery.DiscoveryClient 获取注册在注册中心的服务列表,生成对应的 RouteDefinition 数组。

public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLocator {private final DiscoveryLocatorProperties properties;private final String routeIdPrefix;private final SimpleEvaluationContext evalCtxt;private Flux<List<ServiceInstance>> serviceInstances;}

@Overridepublic Flux<RouteDefinition> getRouteDefinitions() {SpelExpressionParser parser = new SpelExpressionParser();Expression includeExpr = parser.parseExpression(properties.getIncludeExpression());Expression urlExpr = parser.parseExpression(properties.getUrlExpression());//构造服务实例是否可用predicate。Predicate<ServiceInstance> includePredicate;if (properties.getIncludeExpression() == null|| "true".equalsIgnoreCase(properties.getIncludeExpression())) {includePredicate = instance -> true;}else {includePredicate = instance -> {Boolean include = includeExpr.getValue(evalCtxt, instance, Boolean.class);if (include == null) {return false;}return include;};}return serviceInstances.filter(instances -> !instances.isEmpty())//返回可用实例.map(instances -> instances.get(0)).filter(includePredicate).map(instance -> {
//构建definitionRouteDefinition routeDefinition = buildRouteDefinition(urlExpr,instance);final ServiceInstance instanceForEval = new DelegatingServiceInstance(instance, properties);
//拷贝PredicateDefinition for (PredicateDefinition original : this.properties.getPredicates()) {PredicateDefinition predicate = new PredicateDefinition();predicate.setName(original.getName());for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
//计算表达式值。String value = getValueFromExpr(evalCtxt, parser,instanceForEval, entry);predicate.addArg(entry.getKey(), value);}routeDefinition.getPredicates().add(predicate);}
//拷贝FilterDefinition for (FilterDefinition original : this.properties.getFilters()) {FilterDefinition filter = new FilterDefinition();filter.setName(original.getName());for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
//计算表达式值。String value = getValueFromExpr(evalCtxt, parser,instanceForEval, entry);filter.addArg(entry.getKey(), value);}routeDefinition.getFilters().add(filter);}return routeDefinition;});}

RouteLocator解析

RouteLocator

路由定位器接口,定义获得路由数组的方法

public interface RouteLocator {Flux<Route> getRoutes();
}

CompositeRouteLocator

组合多种 RouteLocator 的实现类,为 RoutePredicateHandlerMapping 提供统一入口访问路由

public class CompositeRouteLocator implements RouteLocator {private final Flux<RouteLocator> delegates;public CompositeRouteLocator(Flux<RouteLocator> delegates) {this.delegates = delegates;}@Overridepublic Flux<Route> getRoutes() {return this.delegates.flatMap(RouteLocator::getRoutes);}}

CachingRouteLocator

CachingRouteLocator ,缓存路由的 RouteLocator 实现类。RoutePredicateHandlerMapping 调用 CachingRouteLocator 的 RouteLocator#getRoutes() 方法,获取路由。

public class CachingRouteLocatorimplements Ordered, RouteLocator, ApplicationListener<RefreshRoutesEvent> {private static final String CACHE_KEY = "routes";private final RouteLocator delegate;private final Flux<Route> routes;private final Map<String, List> cache = new ConcurrentHashMap<>();public CachingRouteLocator(RouteLocator delegate) {this.delegate = delegate;routes = CacheFlux.lookup(cache, CACHE_KEY, Route.class).onCacheMissResume(this::fetch);}
}

RouteDefinitionRouteLocator

RouteDefinitionRouteLocator ,基于 RouteDefinitionLocator 的 RouteLocator 实现类。RouteDefinitionRouteLocator 从 RouteDefinitionLocator 获取 RouteDefinition ,转换成 Route

public class RouteDefinitionRouteLocatorimplements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware {/*** Default filters name.*/public static final String DEFAULT_FILTERS = "defaultFilters";protected final Log logger = LogFactory.getLog(getClass());private final RouteDefinitionLocator routeDefinitionLocator;private final ConfigurationService configurationService;private final Map<String, RoutePredicateFactory> predicates = new LinkedHashMap<>();private final Map<String, GatewayFilterFactory> gatewayFilterFactories = new HashMap<>();private final GatewayProperties gatewayProperties;
}

构造函数

public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator,List<RoutePredicateFactory> predicates,List<GatewayFilterFactory> gatewayFilterFactories,GatewayProperties gatewayProperties,ConfigurationService configurationService) {this.routeDefinitionLocator = routeDefinitionLocator;this.configurationService = configurationService;initFactories(predicates);gatewayFilterFactories.forEach(factory -> this.gatewayFilterFactories.put(factory.name(), factory));this.gatewayProperties = gatewayProperties;}

获得 Route

@Overridepublic Flux<Route> getRoutes() {//routeDefinitionLocator获取RouteDefinitions,转换成RouteFlux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions().map(this::convertToRoute);//错误是否抛出异常if (!gatewayProperties.isFailOnRouteDefinitionError()) {// instead of letting error bubble up, continueroutes = routes.onErrorContinue((error, obj) -> {if (logger.isWarnEnabled()) {logger.warn("RouteDefinition id " + ((RouteDefinition) obj).getId()+ " will be ignored. Definition has invalid configs, "+ error.getMessage());}});}return routes.map(route -> {if (logger.isDebugEnabled()) {logger.debug("RouteDefinition matched: " + route.getId());}return route;});}//合并predicate,合并filters,构造一个route。private Route convertToRoute(RouteDefinition routeDefinition) {AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);return Route.async(routeDefinition).asyncPredicate(predicate).replaceFilters(gatewayFilters).build();}

自定义 RouteLocator

RouteLocatorBuilder用于自定义RouteLocator

public class RouteLocatorBuilder {   public Builder routes() {return new Builder(context);}
}
public static class Builder {private List<Route.AsyncBuilder> routes = new ArrayList<>();private ConfigurableApplicationContext context;public Builder(ConfigurableApplicationContext context) {this.context = context;}
}
  • RouteSpec:route builder。
  • UriSpec:可以添加一个Uri
  • PredicateSpec:可以应用到一个Uri的Predicate。
  • BooleanOpSpec:逻辑操作Predicate。
  • GatewayFilterSpec:GatewayFilter

Spring Cloud Gateway 源码解析(2) —— 路由相关推荐

  1. Spring Cloud Gateway 源码解析(1) —— 基础

    目录 Gateway初始化 启用Gateway GatewayClassPathWarningAutoConfiguration GatewayLoadBalancerClientAutoConfig ...

  2. api网关揭秘--spring cloud gateway源码解析

    要想了解spring cloud gateway的源码,要熟悉spring webflux,我的上篇文章介绍了spring webflux. 1.gateway 和zuul对比 I am the au ...

  3. Spring Cloud Gateway 源码解析(3) —— Predicate

    目录 RoutePredicateFactory GatewayPredicate AfterRoutePredicateFactory RoutePredicateHandlerMapping Fi ...

  4. Spring Cloud Gateway 源码解析(4)-- filter

    文章目录 绑定Filter HandlerMapping Filter GatewayFilterChain FilteringWebHandler GlobalFilter实例化 GatewayFi ...

  5. Spring Cloud Gateway源码系列之路由配置加载过程

    当前章节主要是讲解配置文件中定义的路由配置被gateway加载,同时转为可以直接操作的路由对象 引入pom坐标 <dependency><groupId>org.springf ...

  6. Spring cloud Gateway 源码(二) 路由流程

    目录 1.DispatcherHandler 1.1 handle方法 1.1.1 getHandler 获取请求处理器 1.1.2 invokeHandler 执行 2.路由选择 2.1  选择目标 ...

  7. spring cloud ribbon源码解析(一)

    我们知道spring cloud中restTemplate可以通过服务名调接口,加入@loadBalanced标签就实现了负载均衡的功能,那么spring cloud内部是如何实现的呢? 通过@loa ...

  8. spring aop 注入源码解析

    spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...

  9. spring aop 注入源码解析 1

    spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...

最新文章

  1. msvcrt.lib和LIBCD.lib链接冲突
  2. R语言使用pwr包的pwr.r.test函数对相关信息分析(Correlations)进行效用分析(power analysis)的语法
  3. linux定义别名出错,Linux自定义别名alias重启失效问题
  4. 未定义与 double 类型的输入参数相对应的函数 eval_点评一下鸿蒙os的时钟计算函数...
  5. HDU2608 0 or 1
  6. 【CodeForces - 304B】Calendar (前缀和,水题)
  7. Mysql学习总结(59)——数据库分库分表策略总结
  8. shell脚本执行时报bad interpreter: Text file busy的解决方法
  9. java guava cache_java使用guava cache实现本地缓存
  10. linux根据端口号查询项目路径
  11. Codesys中国官网下载中心
  12. c语言色环电阻计算器源代码,色环电阻在线计算器
  13. mysql 不建议delete?
  14. 程序存储器与数据存储器
  15. 内是独体字还是半包围_独体字与半包围的字究竟怎么区分?
  16. 干草堆——acwing算法题第二天
  17. PlayCanvas学习教程总结
  18. University's Little_Mess Note(more) [李园7舍_404]
  19. pr安装无法启动 计算机丢失,为什么pr安装成功却无法启动?
  20. ubuntu20.04如何安装搜狗输入法

热门文章

  1. 由 Windows 向 Linux 迁移字体
  2. 多给明年留些钱 明年必将要火的好手机
  3. 集合对象的声明和初始化
  4. 数据结构-王道-绪论
  5. 光伏电价下调幅度大 短期内市场不明朗
  6. 错误代码: 1054 Unknown column #39;t.createUsrId#39; in #39;group statement#39;
  7. JSON解析---初识
  8. 使用devenv/MSBuild在命令行编译单个project
  9. 窗口和元素的大小:offset client scroll
  10. 在apache访问日志中统计统计前十名pv