目录

Gateway初始化

启用Gateway

GatewayClassPathWarningAutoConfiguration

GatewayLoadBalancerClientAutoConfiguration

GatewayAutoConfiguration

网关的开启和关闭

GlobalFilters

RoutePredicateFactory

NettyConfiguration

核心组件构建

组件

Route

AsyncPredicate

GatewayFilter

Route构建

外部化配置

编程方式

构建原理

GatewayProperties

RouteDefinition

FilterDefinition

PredicateDefinition

RoutePredicateFactory

GatewayFilterFactory

RouteLocator

RouteDefinitionRouteLocator


本文章源码为2.2.2-release,github:https://github.com/spring-cloud/spring-cloud-gateway/tree/v2.2.2.RELEASE

Gateway初始化

启用Gateway

官方示例中,启用Gateway,使用了@EnableAutoConfiguration注解。

@EnableAutoConfiguration
@Import(AdditionalRoutes.class)
public class GatewaySampleApplication {
......
}

@EnableAutoConfiguration注解会引入:

这些自动配置类都放在org.springframework.cloud.gateway.config下。在加载GatewayAutoConfiguration之前,会加载一些配置,通过@AutoConfigureAfter,@AutoConfigureBefore注解来控制加载顺序。

GatewayClassPathWarningAutoConfiguration

用于检查项目是否正确导入 spring-boot-starter-webflux 依赖,而不是错误导入 spring-boot-starter-web 依赖。

@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(GatewayAutoConfiguration.class)
public class GatewayClassPathWarningAutoConfiguration {@Configuration(proxyBeanMethods = false)@ConditionalOnClass(name = "org.springframework.web.servlet.DispatcherServlet")protected static class SpringMvcFoundOnClasspathConfiguration {public SpringMvcFoundOnClasspathConfiguration() {log.warn(BORDER+ "Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. "+ "Please remove spring-boot-starter-web dependency." + BORDER);}}@Configuration(proxyBeanMethods = false)@ConditionalOnMissingClass("org.springframework.web.reactive.DispatcherHandler")protected static class WebfluxMissingFromClasspathConfiguration {public WebfluxMissingFromClasspathConfiguration() {log.warn(BORDER + "Spring Webflux is missing from the classpath, "+ "which is required for Spring Cloud Gateway at this time. "+ "Please add spring-boot-starter-webflux dependency." + BORDER);}}}

GatewayLoadBalancerClientAutoConfiguration

初始化 LoadBalancerClientFilter,可以使用LoadBalancerProperties加载配置信息。

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ LoadBalancerClient.class, RibbonAutoConfiguration.class,DispatcherHandler.class })
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@EnableConfigurationProperties(LoadBalancerProperties.class)
public class GatewayLoadBalancerClientAutoConfiguration {@Bean@ConditionalOnBean(LoadBalancerClient.class)@ConditionalOnMissingBean({ LoadBalancerClientFilter.class,ReactiveLoadBalancerClientFilter.class })public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client,LoadBalancerProperties properties) {return new LoadBalancerClientFilter(client, properties);}}

配置:spring.cloud.gateway.loadbalancer

@ConfigurationProperties("spring.cloud.gateway.loadbalancer")
public class LoadBalancerProperties {private boolean use404;public boolean isUse404() {return use404;}public void setUse404(boolean use404) {this.use404 = use404;}
}

GatewayAutoConfiguration

GatewayAutoConfiguration是Gateway的核心配置类。仅当时reactive类型 服务时才加载。

会初始化一些组件:

  • GlobalFilters
  • RoutePredicateFactory
  • RouteDefinitionLocator
  • NettyConfiguration
  • FilteringWebHandler
  • GatewayProperties
  • PrefixPathGatewayFilterFactory
  • RouteDefinitionLocator
  • RouteLocator
  • RoutePredicateHandlerMapping
  • GatewayWebfluxEndpoint

网关的开启和关闭

从 GatewayAutoConfiguration 上的注解 @ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true) ,我们可以看出 :

  • 通过 spring.cloud.gateway.enabled 配置网关的开启与关闭。
  • matchIfMissing = true   =>   网关默认开启

GlobalFilters

RoutePredicateFactory

NettyConfiguration

核心组件构建

组件

Route

Route 是 gateway 中最基本的组件之一,表示一个具体的路由信息载体。

public class Route implements Ordered {private final String id;private final URI uri;private final int order;private final AsyncPredicate<ServerWebExchange> predicate;private final List<GatewayFilter> gatewayFilters;private final Map<String, Object> metadata;public int getOrder() {return order;}
}

Route 主要定义了如下几个部分:

① id,标识符,区别于其他 Route。

② destination uri,路由指向的目的地 uri,即客户端请求最终被转发的目的地。

③ order,用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高。

④ predicate,谓语,表示匹配该 Route 的前置条件,即满足相应的条件才会被路由到目的地 uri。

⑤ gateway filters,过滤器用于处理切面逻辑,如路由转发前修改请求头等。

AsyncPredicate

Predicate 即 Route 中所定义的部分,用于条件匹配,请参考 Java 8 提供的 Predicate 和 Function。

public interface AsyncPredicate<T> extends Function<T, Publisher<Boolean>> {default AsyncPredicate<T> and(AsyncPredicate<? super T> other) {return new AndAsyncPredicate<>(this, other);}default AsyncPredicate<T> negate() {return new NegateAsyncPredicate<>(this);}default AsyncPredicate<T> or(AsyncPredicate<? super T> other) {return new OrAsyncPredicate<>(this, other);}static AsyncPredicate<ServerWebExchange> from(Predicate<? super ServerWebExchange> predicate) {return new DefaultAsyncPredicate<>(GatewayPredicate.wrapIfNeeded(predicate));}
}

AsyncPredicate 定义了 3 种逻辑操作方法:

① and ,与操作,即两个 Predicate 组成一个,需要同时满足。

② negate,取反操作,即对 Predicate 匹配结果取反。

③ or,或操作,即两个 Predicate 组成一个,只需满足其一。

GatewayFilter

很多框架都有 Filter 的设计,用于实现可扩展的切面逻辑。

public interface GatewayFilter extends ShortcutConfigurable {/*** Name key.*/String NAME_KEY = "name";/*** Value key.*/String VALUE_KEY = "value";/*** Process the Web request and (optionally) delegate to the next {@code WebFilter}* through the given {@link GatewayFilterChain}.* @param exchange the current server exchange* @param chain provides a way to delegate to the next filter* @return {@code Mono<Void>} to indicate when request processing is complete*/Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);}

Filter 最终是通过 filter chain 来形成链式调用的,每个 filter 处理完 pre filter 逻辑后委派给 filter chain,filter chain 再委派给下一下 filter。

public interface GatewayFilterChain {Mono<Void> filter(ServerWebExchange exchange);
}

Route构建

外部化配置

参考:Spring Cloud Gateway介绍(一),Spring Cloud Gateway介绍(二)

编程方式

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { // ①return builder.routes() // ②.route(r -> r.host("**.abc.org").and().path("/image/png") // ③.filters(f ->f.addResponseHeader("X-TestHeader", "foobar")) // ④.uri("http://httpbin.org:80") // ⑤).build();
}

RouteLocatorBuilder 在 spring-cloud-starter-gateway 模块自动装配类中已经声明,可直接使用。RouteLocator 封装了对 Route 获取的定义,可简单理解成工厂模式。

RouteLocatorBuilder 可以构建多个路由信息。

构建原理

GatewayProperties

GatewayProperties 是 Spring cloud gateway 模块提供的外部化配置类。

@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<>(); // ③
}

RouteDefinition

该组件用来对 Route 信息进行定义,最终会被 RouteLocator 解析成 Route。

FilterDefinition

用来定义Filter。

@Validated
public class FilterDefinition {@NotNullprivate String name;private Map<String, String> args = new LinkedHashMap<>();
}

通过构造函数来设置参数。

 public FilterDefinition(String text) {int eqIdx = text.indexOf('=');if (eqIdx <= 0) {setName(text);return;}setName(text.substring(0, eqIdx));String[] args = tokenizeToStringArray(text.substring(eqIdx + 1), ",");for (int i = 0; i < args.length; i++) {this.args.put(NameUtils.generateName(i), args[i]);}}

PredicateDefinition

用于定义 Predicate。

RoutePredicateFactory

RoutePredicateFactory 是所有 predicate factory 的顶级接口,职责就是生产 Predicate。

创建一个用于配置用途的对象(config),以其作为参数应用到 apply方法上来生产一个 Predicate 对象,再将 Predicate 对象包装成 AsyncPredicate。

public interface RoutePredicateFactory<C> extends ShortcutConfigurable, Configurable<C> {/*** Pattern key.*/String PATTERN_KEY = "pattern";// useful for javadsldefault Predicate<ServerWebExchange> apply(Consumer<C> consumer) {C config = newConfig();consumer.accept(config);beforeApply(config);return apply(config);}}

GatewayFilterFactory

GatewayFilterFactory 职责就是生产 GatewayFilter。

@FunctionalInterface
public interface GatewayFilterFactory<C> extends ShortcutConfigurable,Configurable<C> { // ①String NAME_KEY = "name";String VALUE_KEY = "value";GatewayFilter apply(C config); // ②
}

RouteLocator

Route 的定位器或者说探测器,是用来获取 Route 信息的。

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

RouteDefinitionRouteLocator

RouteLocator 最主要的实现类,用于将 RouteDefinition 转换成 Route。

public class RouteDefinitionRouteLocator implements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware {private final RouteDefinitionLocator routeDefinitionLocator;private final Map<String, RoutePredicateFactory> predicates = new LinkedHashMap<>();private final Map<String, GatewayFilterFactory> gatewayFilterFactories = new HashMap<>(); private final GatewayProperties gatewayProperties;private final SpelExpressionParser parser = new SpelExpressionParser();private BeanFactory beanFactory;private ApplicationEventPublisher publisher;}

构造函数

 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;
}

构造函数依赖 4 个对象,分别是:

① RouteDefinition Locator,一个 RouteDefinitionLocator 对象。

② predicates factories,Predicate 工厂列表,会被映射成 key 为 name, value 为 factory 的 Map。可以猜想出 gateway 是如何根据 PredicateDefinition 中定义的 name 来匹配到相对应的 factory 了。

③ filter factories,Gateway Filter 工厂列表,同样会被映射成 key 为 name, value 为 factory 的 Map。

④ gateway properties,外部化配置类。

疑问:该类依赖 GatewayProperties 对象,后者已经携带了 List 结构的 RouteDefinition,那为什么还要依赖 RouteDefinitionLocator 来提供 RouteDefinition?

  1. 这里并不会直接使用到 GatewayProperties 类中的 RouteDefinition,仅是用到其定义的 default filters,这会应用到每一个 Route 上。
  2. 最终传入的 RouteDefinitionLocator 实现上是 CompositeRouteDefinitionLocator 的实例,它组合了 GatewayProperties 中所定义的 routes。

getRoutes()

@Overridepublic Flux<Route> getRoutes() {Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions()  //获取 RouteDefinition.map(this::convertToRoute);  //转换成Route......return routes.map(route -> {if (logger.isDebugEnabled()) {logger.debug("RouteDefinition matched: " + route.getId());}return route;});}
//将 RouteDefinition 转换成 Route。private Route convertToRoute(RouteDefinition routeDefinition) {//将 PredicateDefinition 转换成 AsyncPredicate。AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);//将 FilterDefinition 转换成 GatewayFilter。List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);//生成 Route 对象。return Route.async(routeDefinition).asyncPredicate(predicate).replaceFilters(gatewayFilters).build();}
FilterDefinition 转换成 GatewayFilter
private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {List<GatewayFilter> filters = new ArrayList<>();// TODO: support option to apply defaults after route specific filters?//获取gateway配置的默认的filtersif (!this.gatewayProperties.getDefaultFilters().isEmpty()) {filters.addAll(loadGatewayFilters(DEFAULT_FILTERS,this.gatewayProperties.getDefaultFilters()));}//获取每个route配置的 gatewayFiltersif (!routeDefinition.getFilters().isEmpty()) {filters.addAll(loadGatewayFilters(routeDefinition.getId(),routeDefinition.getFilters()));}//排序AnnotationAwareOrderComparator.sort(filters);return filters;}

PredicateDefinition 转换成 AsyncPredicate

 private AsyncPredicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {//获取配置的route的predicate。List<PredicateDefinition> predicates = routeDefinition.getPredicates();//将列表中第一个 PredicateDefinition 转换成 AsyncPredicate。AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition,predicates.get(0));//循环调用,将列表中每一个 PredicateDefinition 都转换成 AsyncPredicate。for (PredicateDefinition andPredicate : predicates.subList(1,predicates.size())) {AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition,andPredicate);//应用and操作,将所有的 AsyncPredicate 组合成一个 AsyncPredicate 对象。predicate = predicate.and(found);}return predicate;}

lookup

private AsyncPredicate<ServerWebExchange> lookup(RouteDefinition route, PredicateDefinition predicate) {
//根据 predicate 名称获取对应的 predicate factory。RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName());if (factory == null) {throw new IllegalArgumentException("Unable to find RoutePredicateFactory with name             " + predicate.getName());}
//获取 PredicateDefinition 中的 Map 类型参数,key 是固定字符串_genkey_ + 数字拼接而成。Map<String, String> args = predicate.getArgs();// if (logger.isDebugEnabled()) {logger.debug("RouteDefinition " + route.getId() + " applying "+ args + " to " + predicate.getName());}
//对上 步获得的参数作进一步转换,key为 config 类(工厂类中通过范型指定)的属性名称。Map<String, Object> properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory);
//调用 factory 的 newConfig 方法创建一个 config 类对象。Object config = factory.newConfig();
//将上步中产生的参数绑定到 config 对象上。ConfigurationUtils.bind(config, properties,factory.shortcutFieldPrefix(), predicate.getName(),                                     validator); if (this.publisher != null) {this.publisher.publishEvent(new PredicateArgsEvent(this, route.getId(), properties));}
//将 cofing 作参数代入,调用 factory 的 applyAsync 方法创建 AsyncPredicate 对象。return factory.applyAsync(config);
}

Spring Cloud Gateway 源码解析(1) —— 基础相关推荐

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

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

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

    目录 RoutePredicateFactory GatewayPredicate AfterRoutePredicateFactory RoutePredicateHandlerMapping Fi ...

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

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

  4. Spring Cloud Gateway 源码解析(2) —— 路由

    目录 基本组件 路由定位器(RouteDefinitionLocator ) 路由定义(RouteDefinition) PredicateDefinition FilterDefinition Co ...

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

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

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

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

  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. 5招全面扫描网站页面的质量
  2. 超强图文|并发编程【等待/通知机制】就是这个feel~
  3. Nature报道新冠病毒新研究:传猫易,传狗难,猫狗能否传人不明确
  4. php源代码压缩,PHP_PHP 源代码压缩小工具,使用方法:(在命令行运行) 复 - phpStudy...
  5. 12/100. Diameter of Binary Tree
  6. java ee打印功能_Java EE:异步构造和功能
  7. 标杆徐2018 Linux自动化运维实战,标杆徐2018 Linux自动化运维系列⑦: SaltStack自动化配置管理实战...
  8. 运行多个 npm script 的各种姿势
  9. python搭建web服务
  10. 【吴恩达机器学习】学习笔记——1.5无监督学习
  11. @程序员,如何在五分钟内构建个人网盘服务?| 技术头条
  12. 《『若水新闻』客户端开发教程》——11.代码编码(3)
  13. DEM高程数据下载方法
  14. 听完蔡学镛的分享《不瞌睡的PPT制作秘诀》后的总结
  15. 开优步认识各色各样的人,人生需要这样的新鲜体验!
  16. Excel中怎么把经纬度记录转成经纬度数值形式
  17. #199-【莫队】小Z的袜子
  18. 同济大学计算机科学与技术系,同济大学计算机科学与技术系简介_跨考网
  19. 用python玩转数据作业答案_大学mooc2020年用Python玩转数据作业答案
  20. 机器学习——基础概念

热门文章

  1. 产品管理职位的级别都有哪些
  2. ubuntu服务器安装指南
  3. 使用C#开发一个简单的P2P应用
  4. PyQt5:窗口的基本功能
  5. Windows中安装Emacs
  6. S3C2440 IIS操作 uda134x录放音
  7. JavaScript 自执行函数剖析
  8. 测试你的Python 水平----7
  9. 常见多媒体文件格式及视音频编解码总结
  10. [iBoard 电子学堂][第八卷 设计任意波发生器]第一篇 iBoard 任意波发生器简介