本文主要基于 Spring-Cloud-Gateway 2.0.X M4
友情提示:欢迎关注公众号【芋道源码】。😈关注后,拉你进【源码圈】微信群讨论技术和源码。 友情提示:欢迎关注公众号【芋道源码】。😈关注后,拉你进【源码圈】微信群讨论技术和源码。 友情提示:欢迎关注公众号【芋道源码】。😈关注后,拉你进【源码圈】微信群讨论技术和源码。
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
包下,我们可以看到四个配置类 :
它们的初始化顺序如下图 :
推荐 Spring Cloud 书籍:
推荐 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 核心配置类,初始化如下 :
组件关系交互如下图 :
5.1 网关的开启与关闭
从 GatewayAutoConfiguration 上的注解
@ConditionalOnProperty(name = "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: }
- 调用 `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: }
5.4 初始化 FilteringWebHandler
当所有
org.springframework.cloud.gateway.filter.GlobalFilter
初始化完成时( 包括上面的 NettyRoutingFilter / NettyWriteResponseFilter ),创建一个类型为
org.springframework.cloud.gateway.handler.FilteringWebHandler
的 Bean 对象,代码如下 :
@Bean // 2.6
public FilteringWebHandler filteringWebHandler(ListGlobalFilter globalFilters) {
return new FilteringWebHandler(globalFilters);
}
5.5 初始化 GatewayProperties
创建一个类型为
org.springframework.cloud.gateway.config.GatewayProperties
的 Bean 对象,用于加载配置文件配置的 RouteDefinition / FilterDefinition 。代码如下 :
@Bean // 2.7
public GatewayProperties gatewayProperties() {
return new 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(ListRouteDefinitionLocator routeDefinitionLocators) {
16: return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators));
17: }
- 第 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: ListGatewayFilterFactory GatewayFilters,
4: ListRoutePredicateFactory predicates,
5: RouteDefinitionLocator routeDefinitionLocator) {
6: return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties);
7: }
8:
9: @Bean // 4.5
10: @Primary
11: public RouteLocator routeLocator(ListRouteLocator routeLocators) {
12: return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
13: }
- 此处的 `routeDefinitionLocator` 参数,使用了 `@Primary` 注解的 CompositeRouteDefinitionLocator 的 Bean 对象。
-
使用 `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` 的代码实现。
第 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 :
使用
RouteLocatorDsl#gateway()
方法,创建 RouteLocator ,该方式使用 Kotlin 实现,例子代码如下 :
@Configuration
class AdditionalRoutes {<pre style="box-sizing: border-box;margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 2px 4px;color: rgb(248, 35, 117);line-height: 18px;border-radius: 0px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;font-family: Consolas, Inconsolata, Courier, monospace;letter-spacing: 0px;word-wrap: inherit !important;display: block !important;word-break: inherit !important;overflow: auto !important;">@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"))
}
}
}
5.10 初始化 RoutePredicateHandlerMapping
创建一个类型为
org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping
的 Bean 对象,用于查找匹配到 Route ,并进行处理。代码如下 :
@Bean
public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler,
RouteLocator routeLocator) {
return new RoutePredicateHandlerMapping(webHandler, routeLocator);
}
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, ListGlobalFilter globalFilters,
ListGatewayFilterFactory GatewayFilters, RouteDefinitionWriter routeDefinitionWriter,
RouteLocator routeLocator) {
return new GatewayWebfluxEndpoint(routeDefinitionLocator, globalFilters, GatewayFilters, routeDefinitionWriter, routeLocator);
}
}
666. 彩蛋
是不是内心里面有种感觉,“劳资看了一堆构造函数”?
嘿嘿嘿,后面咱一篇一篇走起!
胖友,分享一波朋友圈可好!