网关 Spring-Cloud-Gateway 源码解析 —— 网关初始化

本文主要基于 Spring-Cloud-Gateway 2.0.X M4

  • 1. 概述
  • 2. GatewayClassPathWarningAutoConfiguration
  • 3. GatewayLoadBalancerClientAutoConfiguration
  • 4. GatewayRedisAutoConfiguration
  • 5. GatewayAutoConfiguration

1. 概述

本文主要分享 Spring Cloud Gateway 启动初始化的过程

在初始化的过程中,涉及到的组件会较多,本文不会细说,留到后面每篇文章针对每个组件详细述说。

那么这有什么意义呢?先对 Spring Cloud Gateway 内部的组件有整体的印象。


在官方提供的实例项目 spring-cloud-gateway-sample ,我们看到 GatewaySampleApplication 上有 @EnableAutoConfiguration 注解。因为该项目导入了 spring-cloud-gateway-core 依赖库,它会扫描 Spring Cloud Gateway 的配置。

org.springframework.cloud.gateway.config 包下,我们可以看到四个配置类 :

  • GatewayAutoConfiguration
  • GatewayClassPathWarningAutoConfiguration
  • GatewayLoadBalancerClientAutoConfiguration
  • GatewayRedisAutoConfiguration

它们的初始化顺序如下图 :


推荐 Spring Cloud 书籍

  • 请支持正版。下载盗版,等于主动编写低级 BUG
  • 程序猿DD —— 《Spring Cloud微服务实战》
  • 周立 —— 《Spring Cloud与Docker微服务架构实战》
  • 两书齐买,京东包邮。

推荐 Spring Cloud 视频

  • Java 微服务实践 - Spring Boot
  • Java 微服务实践 - Spring Cloud
  • Java 微服务实践 - Spring Boot / Spring Cloud

2. GatewayClassPathWarningAutoConfiguration

Spring Cloud Gateway 2.x 基于 Spring WebFlux 实现。

org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration ,用于检查项目是否正确导入 spring-boot-starter-webflux 依赖,而不是错误导入 spring-boot-starter-web 依赖。

点击链接 链接 查看 GatewayClassPathWarningAutoConfiguration 的代码实现。

3. GatewayLoadBalancerClientAutoConfiguration

org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration ,初始化 LoadBalancerClientFilter ,点击 链接 查看代码。

在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.4) 之 LoadBalancerClientFilter 负载均衡》 详细解析 LoadBalancerClientFilter 的代码实现。

4. GatewayRedisAutoConfiguration

org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration ,初始化 RedisRateLimiter 。

RequestRateLimiterGatewayFilterFactory 基于 RedisRateLimiter 实现网关的限流功能,在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.10) 之 RequestRateLimiterGatewayFilterFactory 请求限流》 详细解析相关的代码实现。

5. GatewayAutoConfiguration

org.springframework.cloud.gateway.config.GatewayAutoConfiguration ,Spring Cloud Gateway 核心配置类,初始化如下 :

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

组件关系交互如下图 :

5.1 网关的开启与关闭

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

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

5.2 初始化 NettyConfiguration

org.springframework.cloud.gateway.config.NettyConfiguration ,Netty 配置类。代码如下 :

  1: @Configuration
  2: @ConditionalOnClass(HttpClient.class)
  3: protected static class NettyConfiguration {
  4:     @Bean // 1.2
  5:     @ConditionalOnMissingBean
  6:     public HttpClient httpClient(@Qualifier("nettyClientOptions") Consumer<? super HttpClientOptions.Builder> options) {
  7:         return HttpClient.create(options);
  8:     }
  9: 
 10:     @Bean // 1.1
 11:     public Consumer<? super HttpClientOptions.Builder> nettyClientOptions() {
 12:         return opts -> {
 13:             opts.poolResources(PoolResources.elastic("proxy"));
 14:             // opts.disablePool(); //TODO: why do I need this again?
 15:         };
 16:     }
 17: 
 18:     @Bean // 1.3
 19:     public NettyRoutingFilter routingFilter(HttpClient httpClient) {
 20:         return new NettyRoutingFilter(httpClient);
 21:     }
 22: 
 23:     @Bean // 1.4
 24:     public NettyWriteResponseFilter nettyWriteResponseFilter() {
 25:         return new NettyWriteResponseFilter();
 26:     }
 27: 
 28:     @Bean // 1.5 {@link org.springframework.cloud.gateway.filter.WebsocketRoutingFilter}
 29:     public ReactorNettyWebSocketClient reactorNettyWebSocketClient(@Qualifier("nettyClientOptions") Consumer<? super HttpClientOptions.Builder> options) {
 30:         return new ReactorNettyWebSocketClient(options);
 31:     }
 32: }
  • 每个 @Bean 注解后的数字为 Bean 的初始化顺序
  • 第 10 至 16 行 :创建一个类型为 java.util.Objects.Consumer 的 Bean 对象。该 Consumer 会将传入类型为 reactor.ipc.netty.options.HttpClientOptions.Builder 的参数 opts ,设置 optspoolResources 属性。
    • 调用 PoolResources.elastic("proxy") 方法,创建 name 属性为 "proxy"reactor.ipc.netty.resources.PoolResources 。其中 "proxy" 用于实际使用时,打印日志的标记
  • 第 4 至 8 行 :创建一个类型为 reactor.ipc.netty.http.client.HttpClient 的 Bean 对象。该 HttpClient 使用 Netty 实现的 Client 。
  • 第 18 至 21 行 :使用 HttpClient Bean ,创建一个类型为 org.springframework.cloud.gateway.filter.NettyRoutingFilter 的 Bean 对象。在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.7) 之 NettyRoutingFilter》 详细解析 NettyRoutingFilter 的代码实现。
  • 第 23 至 26 行 :创建一个类型为 org.springframework.cloud.gateway.filter.NettyWriteResponseFilter 的 Bean 对象。在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.7) 之 NettyRoutingFilter》 详细解析 NettyWriteResponseFilter 的代码实现。
  • 第 28 至 31 行 :创建一个类型为 org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient的 Bean 对象,用于下文 WebsocketRoutingFilter 的 Bean 对象创建。

5.3 初始化 GlobalFilter

代码如下 :

  1: @Bean // 2.1
  2: public RouteToRequestUrlFilter routeToRequestUrlFilter() {
  3:     return new RouteToRequestUrlFilter();
  4: }
  5: 
  6: @Bean // 2.2
  7: @ConditionalOnBean(DispatcherHandler.class)
  8: public ForwardRoutingFilter forwardRoutingFilter(DispatcherHandler dispatcherHandler) {
  9:     return new ForwardRoutingFilter(dispatcherHandler);
 10: }
 11: 
 12: @Bean // 2.3
 13: public WebSocketService webSocketService() {
 14:     return new HandshakeWebSocketService();
 15: }
 16: 
 17: @Bean // 2.4
 18: public WebsocketRoutingFilter websocketRoutingFilter(WebSocketClient webSocketClient, WebSocketService webSocketService) {
 19:     return new WebsocketRoutingFilter(webSocketClient, webSocketService);
 20: }
  • 每个 @Bean 注解后的数字为 Bean 的初始化顺序
  • 第 1 至 4 行 :创建一个类型为 org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter 的 Bean 对象。在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.3) 之 RouteToRequestUrlFilter》 详细解析 RouteToRequestUrlFilter 的代码实现。
  • 第 6 至 10 行 :创建一个类型为 org.springframework.cloud.gateway.filter.ForwardRoutingFilter 的 Bean 对象。在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.5) 之 ForwardRoutingFilter》 详细解析 ForwardRoutingFilter 的代码实现。
  • 第 12 至 15 行 :创建一个类型为 org.springframework.web.reactive.socket.server.WebSocketService 的 Bean 对象。
  • 第 17 至 20 行 :创建一个类型为 org.springframework.cloud.gateway.filter.WebsocketRoutingFilter 的 Bean 对象。在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.6) 之 WebsocketRoutingFilter》 详细解析 WebsocketRoutingFilter 的代码实现。

5.4 初始化 FilteringWebHandler

当所有 org.springframework.cloud.gateway.filter.GlobalFilter 初始化完成时( 包括上面的 NettyRoutingFilter / NettyWriteResponseFilter ),创建一个类型为 org.springframework.cloud.gateway.handler.FilteringWebHandler 的 Bean 对象,代码如下 :

@Bean // 2.6
public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
    return new FilteringWebHandler(globalFilters);
}
  • 在 《Spring-Cloud-Gateway 源码解析 —— 处理器 (3.3) 之 FilteringWebHandler 创建过滤器链 》 详细解析 FilteringWebHandler 的代码实现。

5.5 初始化 GatewayProperties

创建一个类型为 org.springframework.cloud.gateway.config.GatewayProperties 的 Bean 对象,用于加载配置文件配置的 RouteDefinition / FilterDefinition 。代码如下 :

@Bean // 2.7
public GatewayProperties gatewayProperties() {
    return new GatewayProperties();
}
  • 在 《Spring-Cloud-Gateway 源码解析 —— 路由(1.2)之 PropertiesRouteDefinitionLocator 配置文件》「3. GatewayProperties」 详细解析 GatewayProperties 的代码实现。

5.6 初始化 PrefixPathGatewayFilterFactory

在 链接 的【第 288 至 372 行】,创建 org.springframework.cloud.gateway.filter.factory包下的 org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory 接口的实现们。

后续我们会对每个 GatewayFilterFactory 的实现代码做详细解析。

5.7 初始化 RoutePredicateFactory

在 链接 的【第 236 至 284 行】,创建 org.springframework.cloud.gateway.handler.predicate 包下的 org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory 接口的实现们。

后续我们会对每个 RoutePredicateFactory 的实现代码做详细解析。

5.8 初始化 RouteDefinitionLocator

代码如下 :

  1: @Bean // 4.1
  2: @ConditionalOnMissingBean
  3: public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
  4:     return new PropertiesRouteDefinitionLocator(properties);
  5: }
  6: 
  7: @Bean // 4.2
  8: @ConditionalOnMissingBean(RouteDefinitionRepository.class)
  9: public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
 10:     return new InMemoryRouteDefinitionRepository();
 11: }
 12: 
 13: @Bean // 4.3
 14: @Primary // 优先被注入
 15: public RouteDefinitionLocator routeDefinitionLocator(List<RouteDefinitionLocator> routeDefinitionLocators) {
 16:     return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators));
 17: }
  • 每个 @Bean 注解后的数字为 Bean 的初始化顺序
  • 第 1 至 5 行 :使用 GatewayProperties Bean ,创建一个类型为 org.springframework.cloud.gateway.config.PropertiesRouteDefinitionLocator 的 Bean 对象。在 《Spring-Cloud-Gateway 源码解析 —— 路由(1.2)之 PropertiesRouteDefinitionLocator 配置文件》「2. PropertiesRouteDefinitionLocator」 详细解析 PropertiesRouteDefinitionLocator 的代码实现。
  • 第 7 至 11 行 :创建一个类型为 org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository 的 Bean 对象。在 《Spring-Cloud-Gateway 源码解析 —— 路由(1.3)之 RouteDefinitionRepository 存储器》 详细解析 InMemoryRouteDefinitionRepository 的代码实现。
  • 第 13 至 17 行 :使用上面创建的 RouteDefinitionLocator 的 Bean 对象们,创建一个类型为 org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator 的 Bean 对象。
    • 第 14 行的 @Primary 注解,用于下文注入类型为 RouteDefinitionLocator 的 Bean 对象时,使用该对象。点击 《spring中少用的注解@primary解析》 查看 @Primary 的详细介绍。

org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator ,基于 DiscoveryClient 注册发现的 RouteDefinitionLocator 实现类,需要手动引入配置,点击 链接 查看。在 《Spring-Cloud-Gateway 源码解析 —— 路由(1.4)之 DiscoveryClientRouteDefinitionLocator 注册中心》 详细解析 DiscoveryClientRouteDefinitionLocator 的代码实现。

5.9 初始化 RouteLocator

代码如下 :

  1: @Bean // 4.4
  2: public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
  3:                                                List<GatewayFilterFactory> GatewayFilters,
  4:                                                List<RoutePredicateFactory> predicates,
  5:                                                RouteDefinitionLocator routeDefinitionLocator) {
  6:     return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties);
  7: }
  8: 
  9: @Bean // 4.5
 10: @Primary
 11: public RouteLocator routeLocator(List<RouteLocator> routeLocators) {
 12:     return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
 13: }
  • 每个 @Bean 注解后的数字为 Bean 的初始化顺序
  • 第 1 至 7 行 :创建一个类型为 org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator 的 Bean 对象。在 《Spring-Cloud-Gateway 源码解析 —— 路由(2.2)之 RouteDefinitionRouteLocator 路由配置》 详细解析 RouteDefinitionRouteLocator 的代码实现。
    • 此处的 routeDefinitionLocator 参数,使用了 @Primary 注解的 CompositeRouteDefinitionLocator 的 Bean 对象。
  • 第 9 至 13 行 :创建一个类型为 org.springframework.cloud.gateway.route.CachingRouteLocator 的 Bean 对象。该 Bean 对象内嵌 org.springframework.cloud.gateway.route.CompositeRouteLocator 对象。在 《Spring-Cloud-Gateway 源码解析 —— 路由(2.1)之 RouteLocator 一览》 详细解析 CachingRouteLocator / CompositeRouteLocator 的代码实现。

另外,有如下两种方式实现自定义 RouteLocator :

  • 使用 Routes#locator()#build() 方法,创建 RouteLocator ,例子代码如下 : @Bean public RouteLocator customRouteLocator() { //@formatter:off return Routes.locator() .route("test") .predicate(host("**.abc.org").and(path("/image/png"))) .addResponseHeader("X-TestHeader", "foobar") .uri("http://httpbin.org:80") .route("test2") .predicate(path("/image/webp")) .add(addResponseHeader("X-AnotherHeader", "baz")) .uri("http://httpbin.org:80") .build(); ////@formatter:on }
    • 在 《Spring-Cloud-Gateway 源码解析 —— 路由(2.3)之 Java 自定义 RouteLocator》 详细解析 org.springframework.cloud.gateway.route.Routes 的代码实现。
  • 使用 RouteLocatorDsl#gateway() 方法,创建 RouteLocator ,该方式使用 Kotlin 实现例子代码如下 : @Configuration class AdditionalRoutes {@Bean fun additionalRouteLocator(): RouteLocator = gateway { route(id = "test-kotlin") { uri("http://httpbin.org:80") predicate(host("kotlin.abc.org") and path("/image/png")) add(addResponseHeader("X-TestHeader", "foobar")) } } }
    • 在 《Spring-Cloud-Gateway 源码解析 —— 路由(2.4)之 Kotlin 自定义 RouteLocator 》 详细解析 org.springframework.cloud.gateway.route.RouteLocatorDsl 的代码实现。

5.10 初始化 RoutePredicateHandlerMapping

创建一个类型为 org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping 的 Bean 对象,用于查找匹配到 Route ,并进行处理。代码如下 :

@Bean
public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler,
                                                                   RouteLocator routeLocator) {
    return new RoutePredicateHandlerMapping(webHandler, routeLocator);
}
  • 在 《Spring-Cloud-Gateway 源码解析 —— 处理器 (3.2) 之 RoutePredicateHandlerMapping 路由匹配 》详细解析 RoutePredicateHandlerMapping 的代码实现。

5.11 初始化 GatewayWebfluxEndpoint

创建一个类型为 org.springframework.cloud.gateway.actuate.GatewayWebfluxEndpoint 的 Bean 对象,提供管理网关的 HTTP API ,代码如下 :

@ManagementContextConfiguration
@ConditionalOnProperty(value = "management.gateway.enabled", matchIfMissing = true)
@ConditionalOnClass(Health.class)
protected static class GatewayActuatorConfiguration {

    @Bean
    public GatewayWebfluxEndpoint gatewayWebfluxEndpoint(RouteDefinitionLocator routeDefinitionLocator, List<GlobalFilter> globalFilters,

        List<GatewayFilterFactory> GatewayFilters, RouteDefinitionWriter routeDefinitionWriter,
                                                         RouteLocator routeLocator) {
        return new GatewayWebfluxEndpoint(routeDefinitionLocator, globalFilters, GatewayFilters, routeDefinitionWriter, routeLocator);
    }
}
  • 在 《Spring-Cloud-Gateway 源码解析 —— 网关管理 HTTP API》 详细解析 GatewayWebfluxEndpoint 的代码实现。

原文发布于微信公众号 - 芋道源码(YunaiV)

原文发表时间:2018-04-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏me的随笔

ASP.NET Web API 2中的错误处理

前几天在webapi项目中遇到一个问题:Controller构造函数中抛出异常时全局过滤器捕获不到,于是网搜一把写下这篇博客作为总结。

813
来自专栏Java Edge

责任链模式

3396
来自专栏Java帮帮-微信公众号-技术文章全总结

day05.轻量级RPC框架【大数据教程】

day05.轻量级RPC框架【大数据教程】 轻量级RPC框架开发 1. RPC原理学习 1.1. 什么是RPC RPC(Remote Procedure Cal...

3037
来自专栏Python自动化测试

Jmeter4.0接口测试之断言实战(六)

在接口测试用例中得有断言,没有断言的接口用例是无效的,一个接口的断言有三个层面,一个是HTTP状态码的断言,另外一个是业务状态码的断言,最后是某一接口请求后服...

994
来自专栏码农阿宇

国内开源社区巨作AspectCore-Framework入门

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技...

1191
来自专栏Java技术栈

Spring Boot 2.x 启动全过程源码分析(全)

上篇《Spring Boot 2.x 启动全过程源码分析(一)入口类剖析》我们分析了 Spring Boot 入口类 SpringApplication 的源码...

1284
来自专栏吴伟祥

手写tomcat监控工具---宕机重启 原

1293
来自专栏青枫的专栏

【重要】Spring在web.xml中的配置原理说明

503
来自专栏韩东吉的Unity杂货铺

零基础入门 36:代码控制预设

上一篇分享给大家带来了如何通过菜单栏呼出一个自定义的窗口,不知道大家消化的如何了呢?

734
来自专栏GreenLeaves

Common.Logging源码解析一

Common.Logging是Apache下的一个开源日志接口组件,主要用于切换不同的日志库,因为当前流行的日志库有很多向log4j、log4net(log4j...

17810

扫码关注云+社区