Spring Cloud Gateway 源码剖析之配置初始化

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
传统型负载均衡 CLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
简介: Spring Cloud Gateway 源码剖析之配置初始化

一、前言

相信大多数公司都会有自己公司的专有网关服务,虽说是自研,但很少会有从零开始开发一个网关服务,基本上是基于市面上比较流行的网关组件像 Zuul、Gateway、Soul 等进行二次封装的。那如果自己公司有相应的网关业务需求的话,这就要对网关产品的底层原理要比较熟悉了,这样做起来也比较顺手。本系列只针对 Gateway 组件进行源码剖析,我在想第一篇如何说会比较好,本来想直接说核心流程的,想了想还是先从配置初始化说起。话不多说,接下来我们就开始 Spring Cloud Gateway 源码剖析之旅吧。

二、揭秘配置初始化

那我们就从项目中 maven 依赖的 jar 包开始吧。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

直接跟进去发现有三个依赖,凭借我们的开发经验,盲猜一下 spring-cloud-gateway-core 就是 gateway 的核心依赖。

直接找到对应的 maven 依赖包:

不知道大家有没有什么疑问,找了这个包,然后 gateway 是怎么与 Spring Boot 项目相关联的呢?

相信有一定经验的朋友知道 Spring Boot 启动的时候有个 @SpringBootApplication 注解,而这个注解包含了一个非常重要的子注解 @EnableAutoConfiguration,该注解表示开启自动配置功能,是 Spring Boot 框架最重要的注解,也是实现自动化配置的注解。

Spring Cloud Gateway 也是同样的套路,那我们直接找到 /META-INF/spring.factories 文件,果不其然。

// Auto Configure

org.springframework.boot.autoconfigure.EnableAutoConfiguration=

// 依赖包的校验配置

org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration,

// 网关的核心配置

org.springframework.cloud.gateway.config.GatewayAutoConfiguration,

// 负载均衡相关依赖配置信息

org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration,

// 度量相关依赖配置信息

org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,

// 流控的依赖配置信息

org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,

// 注册中心相关的依赖配置

org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration

分析上面的自动配置之前,我们先来了解下 SpringBoot 常用注解的含义。

// 执行顺序

@AutoConfigureBefore:在指定的配置类初始化前加载

@AutoConfigureAfter:在指定的配置类初始化后再加载

@AutoConfigureOrder:数越小越先初始化

// 条件配置

@ConditionalOnClass :classpath中存在该类时起效

@ConditionalOnMissingClass :classpath中不存在该类时起效

@ConditionalOnBean :DI容器中存在该类型Bean时起效

@ConditionalOnMissingBean :DI容器中不存在该类型Bean时起效

@ConditionalOnSingleCandidate :DI容器中该类型Bean只有一个或@Primary的只有一个时起效

@ConditionalOnExpression :SpEL表达式结果为true时

@ConditionalOnProperty :参数设置或者值一致时起效

@ConditionalOnResource :指定的文件存在时起效

@ConditionalOnJndi :指定的JNDI存在时起效

@ConditionalOnJava :指定的Java版本存在时起效

@ConditionalOnWebApplication :Web应用环境下起效

@ConditionalOnNotWebApplication :非Web应用环境下起效

1、GatewayClassPathWarningAutoConfiguration

GatewayClassPathWarningAutoConfiguration 用于检查项目是否正确导入 spring-boot-starter-webflux 依赖,而不是错误导入 spring-boot-starter-web 依赖,同时 GatewayClassPathWarningAutoConfiguration 在 EnableAutoConfiguration 配置加载前加载。

@Configuration
// 执行顺序注解
// 当前注解标识需要在GatewayAutoConfiguration前加载此配置
@AutoConfigureBefore({GatewayAutoConfiguration.class})
public class GatewayClassPathWarningAutoConfiguration {
    private static final Log log = LogFactory.getLog(GatewayClassPathWarningAutoConfiguration.class);
    private static final String BORDER = "\n\n**********************************************************\n\n";
    public GatewayClassPathWarningAutoConfiguration() {
    }
    @Configuration
    // 条件判断注解
    // classpath中不存在org.springframework.web.reactive.DispatcherHandler时起效,标识项目未导入了spring-boot-starter-webflux包
    @ConditionalOnMissingClass({"org.springframework.web.reactive.DispatcherHandler"})
    protected static class WebfluxMissingFromClasspathConfiguration {
        public WebfluxMissingFromClasspathConfiguration() {
            // 当前项目未导入了spring-boot-starter-webflux依赖时,打印警告日志
            GatewayClassPathWarningAutoConfiguration.log.warn("\n\n**********************************************************\n\nSpring Webflux is missing from the classpath, which is required for Spring Cloud Gateway at this time. Please add spring-boot-starter-webflux dependency.\n\n**********************************************************\n\n");
        }
    }
    @Configuration
    // 条件判断注解
    // classpath中存在org.springframework.web.servlet.DispatcherServlet时起效,标识项目导入了spring-boot-starter-web包
    @ConditionalOnClass(
        name = {"org.springframework.web.servlet.DispatcherServlet"}
    )
    protected static class SpringMvcFoundOnClasspathConfiguration {
        public SpringMvcFoundOnClasspathConfiguration() {
            // 当前项目导入了spring-boot-starter-web依赖时,打印警告日志
            GatewayClassPathWarningAutoConfiguration.log.warn("\n\n**********************************************************\n\nSpring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. Please remove spring-boot-starter-web dependency.\n\n**********************************************************\n\n");
        }
    }
}


2、GatewayAutoConfiguration

GatewayAutoConfiguration 是 Spring Cloud Gateway 核心配置类,这里只列几个核心的,初始化如下 :

  • RoutePredicateHandlerMapping:查找匹配到 Route 并进行处理
  • GatewayProperties:加载网关配置
  • RouteDefinitionRouteLocator:创建一个根据 RouteDefinition 转换的路由定位器
  • GatewayWebfluxEndpoint:管理网关的 HTTP API


@Configuration
// 条件注解
// 通过 spring.cloud.gateway.enabled 配置网关的开启与关闭
// matchIfMissing = true => 网关默认开启。
@ConditionalOnProperty(
    name = {"spring.cloud.gateway.enabled"},
    matchIfMissing = true
)
@EnableConfigurationProperties
@AutoConfigureBefore({HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class})
@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})
@ConditionalOnClass({DispatcherHandler.class})
public class GatewayAutoConfiguration {
    public GatewayAutoConfiguration() {
    }
    @Bean
    public StringToZonedDateTimeConverter stringToZonedDateTimeConverter() {
        return new StringToZonedDateTimeConverter();
    }
    @Bean
    public RouteLocatorBuilder routeLocatorBuilder(ConfigurableApplicationContext context) {
        return new RouteLocatorBuilder(context);
    }
    @Bean
    @ConditionalOnMissingBean
    public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
        return new PropertiesRouteDefinitionLocator(properties);
    }
    @Bean
    @ConditionalOnMissingBean({RouteDefinitionRepository.class})
    public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
        return new InMemoryRouteDefinitionRepository();
    }
    @Bean
    @Primary
    public RouteDefinitionLocator routeDefinitionLocator(List<RouteDefinitionLocator> routeDefinitionLocators) {
        return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators));
    }
    @Bean
    public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties, List<GatewayFilterFactory> GatewayFilters, List<RoutePredicateFactory> predicates, RouteDefinitionLocator routeDefinitionLocator, @Qualifier("webFluxConversionService") ConversionService conversionService) {
        return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties, conversionService);
    }
    @Bean
    @Primary
    public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
        return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
    }
    @Bean
    public RouteRefreshListener routeRefreshListener(ApplicationEventPublisher publisher) {
        return new RouteRefreshListener(publisher);
    }
    @Bean
    public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
        return new FilteringWebHandler(globalFilters);
    }
    @Bean
    public GlobalCorsProperties globalCorsProperties() {
        return new GlobalCorsProperties();
    }
    @Bean
    public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties, Environment environment) {
        return new RoutePredicateHandlerMapping(webHandler, routeLocator, globalCorsProperties, environment);
    }
    @Bean
    public GatewayProperties gatewayProperties() {
        return new GatewayProperties();
    }
    ...
}


3、GatewayLoadBalancerClientAutoConfiguration

GatewayLoadBalancerClientAutoConfiguration 作用是初始化 LoadBalancerClientFilter 路由的负载均衡拦截器

@Configuration
// 条件判断注解
// classpath中存在LoadBalancerClient和RibbonAutoConfiguration和DispatcherHandler时此配置起效
@ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class, DispatcherHandler.class})
// 执行顺序注解
@AutoConfigureAfter({RibbonAutoConfiguration.class})
@EnableConfigurationProperties({LoadBalancerProperties.class})
public class GatewayLoadBalancerClientAutoConfiguration {
    public GatewayLoadBalancerClientAutoConfiguration() {
    }
    @Bean
    // 条件判断注解
    // DI容器中存在LoadBalancerClient类型Bean时起效
    @ConditionalOnBean({LoadBalancerClient.class})
    @ConditionalOnMissingBean({LoadBalancerClientFilter.class})
    public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client, LoadBalancerProperties properties) {
        return new LoadBalancerClientFilter(client, properties);
    }
}

4、GatewayMetricsAutoConfiguration

GatewayMetricsAutoConfiguration 作用是初始化 GatewayMetricsFilter 路由的度量拦截器

@Configuration
@ConditionalOnProperty(
    name = {"spring.cloud.gateway.enabled"},
    matchIfMissing = true
)
@AutoConfigureBefore({HttpHandlerAutoConfiguration.class})
@AutoConfigureAfter({MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class})
@ConditionalOnClass({DispatcherHandler.class, MeterRegistry.class, MetricsAutoConfiguration.class})
public class GatewayMetricsAutoConfiguration {
    public GatewayMetricsAutoConfiguration() {
    }
    @Bean
    @ConditionalOnBean({MeterRegistry.class})
    @ConditionalOnProperty(
        name = {"spring.cloud.gateway.metrics.enabled"},
        matchIfMissing = true
    )
    public GatewayMetricsFilter gatewayMetricFilter(MeterRegistry meterRegistry) {
        return new GatewayMetricsFilter(meterRegistry);
    }
}

5、GatewayRedisAutoConfiguration

GatewayRedisAutoConfiguration 配置作用是初始化初始化 RedisRateLimiter 限流功能的,RequestRateLimiterGatewayFilterFactory 基于 RedisRateLimiter 实现网关的限流功能。

@Configuration
@AutoConfigureAfter({RedisReactiveAutoConfiguration.class})
@AutoConfigureBefore({GatewayAutoConfiguration.class})
@ConditionalOnBean({ReactiveRedisTemplate.class})
@ConditionalOnClass({RedisTemplate.class, DispatcherHandler.class})
class GatewayRedisAutoConfiguration {
    GatewayRedisAutoConfiguration() {
    }
    @Bean
    public RedisScript redisRequestRateLimiterScript() {
        DefaultRedisScript redisScript = new DefaultRedisScript();
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("META-INF/scripts/request_rate_limiter.lua")));
        redisScript.setResultType(List.class);
        return redisScript;
    }
    @Bean
    public ReactiveRedisTemplate<String, String> stringReactiveRedisTemplate(ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) {
        RedisSerializer<String> serializer = new StringRedisSerializer();
        RedisSerializationContext<String, String> serializationContext = RedisSerializationContext.newSerializationContext().key(serializer).value(serializer).hashKey(serializer).hashValue(serializer).build();
        return new ReactiveRedisTemplate(reactiveRedisConnectionFactory, serializationContext);
    }
    @Bean
    @ConditionalOnMissingBean
    public RedisRateLimiter redisRateLimiter(ReactiveRedisTemplate<String, String> redisTemplate, @Qualifier("redisRequestRateLimiterScript") RedisScript<List<Long>> redisScript, Validator validator) {
        return new RedisRateLimiter(redisTemplate, redisScript, validator);
    }
}

6、GatewayDiscoveryClientAutoConfiguration

GatewayDiscoveryClientAutoConfiguration 的作用是初始化配置路由中的注册发现服务信息

@Configuration
// 同2
@ConditionalOnProperty(
    name = {"spring.cloud.gateway.enabled"},
    matchIfMissing = true
)
@AutoConfigureBefore({GatewayAutoConfiguration.class})
@AutoConfigureAfter({CompositeDiscoveryClientAutoConfiguration.class})
@ConditionalOnClass({DispatcherHandler.class, DiscoveryClient.class})
@EnableConfigurationProperties
public class GatewayDiscoveryClientAutoConfiguration {
    public GatewayDiscoveryClientAutoConfiguration() {
    }
    @Bean
    // 当classpath中存在DiscoveryClient起效
    @ConditionalOnBean({DiscoveryClient.class})
    // 通过spring.cloud.gateway.discovery.locator.enabled配置注册中心查找的开启与关闭
    @ConditionalOnProperty(
        name = {"spring.cloud.gateway.discovery.locator.enabled"}
    )
    public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {
        return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);
    }
    @Bean
    public DiscoveryLocatorProperties discoveryLocatorProperties() {
        DiscoveryLocatorProperties properties = new DiscoveryLocatorProperties();
        properties.setPredicates(initPredicates());
        properties.setFilters(initFilters());
        return properties;
    }
    public static List<PredicateDefinition> initPredicates() {
        ArrayList<PredicateDefinition> definitions = new ArrayList();
        PredicateDefinition predicate = new PredicateDefinition();
        predicate.setName(NameUtils.normalizeRoutePredicateName(PathRoutePredicateFactory.class));
        predicate.addArg("pattern", "'/'+serviceId+'/**'");
        definitions.add(predicate);
        return definitions;
    }
    public static List<FilterDefinition> initFilters() {
        ArrayList<FilterDefinition> definitions = new ArrayList();
        FilterDefinition filter = new FilterDefinition();
        filter.setName(NameUtils.normalizeFilterFactoryName(RewritePathGatewayFilterFactory.class));
        String regex = "'/' + serviceId + '/(?<remaining>.*)'";
        String replacement = "'/${remaining}'";
        filter.addArg("regexp", regex);
        filter.addArg("replacement", replacement);
        definitions.add(filter);
        return definitions;
    }
}

三、总结

通过自动加载初始化上述六个配置实例,Spring Cloud Gateway 就完成自身的加载和初始化工作。跟着老周下来应该还算清晰吧,下一篇我们来说一下 Route 数据模型,敬请期待~



欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。


喜欢的话,点赞、再看、分享三连。

相关文章
|
2月前
|
Java 关系型数据库 MySQL
Spring Boot自动配置:魔法背后的秘密
Spring Boot 自动配置揭秘:只需简单配置即可启动项目,背后依赖“约定大于配置”与条件化装配。核心在于 `@EnableAutoConfiguration` 注解与 `@Conditional` 系列条件判断,通过 `spring.factories` 或 `AutoConfiguration.imports` 加载配置类,实现按需自动装配 Bean。
|
2月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
|
1月前
|
前端开发 Java 应用服务中间件
《深入理解Spring》 Spring Boot——约定优于配置的革命者
Spring Boot基于“约定优于配置”理念,通过自动配置、起步依赖、嵌入式容器和Actuator四大特性,简化Spring应用的开发与部署,提升效率,降低门槛,成为现代Java开发的事实标准。
|
2月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
517 5
|
2月前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
1月前
|
缓存 JSON NoSQL
别再手写过滤器!SpringCloud Gateway 内置30 个,少写 80% 重复代码
小富分享Spring Cloud Gateway内置30+过滤器,涵盖请求、响应、路径、安全等场景,无需重复造轮子。通过配置实现Header处理、限流、重试、熔断等功能,提升网关开发效率,避免代码冗余。
256 1
|
4月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
323 0
|
5月前
|
缓存 监控 Java
说一说 SpringCloud Gateway 堆外内存溢出排查
我是小假 期待与你的下一次相遇 ~
752 5
|
5月前
|
Java API Nacos
|
11月前
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
966 69
利用Spring Cloud Gateway Predicate优化微服务路由策略

热门文章

最新文章