-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Spring Cloud Gateway配置路由主要有两种方式:一种是用yml配置文件,一种是写代码里,这两种方式都是不支持动态配置的。
现实生产环境中,使用Spring Cloud Gateway都是作为所有流量的入口,为了保证系统的高可用,尽量避免系统的重启,所以需要Spring Cloud Gateway的动态路由来处理。
首先我们来看看gateway是如何加载这些配置信息的。
注:本篇 Spring Boot版本为 2.3.0.RELEASE,Spring Cloud版本为Hoxton.SR5,spring-cloud-gateway版本为2.2.3.RELEASE。
1、路由初始化
无论是yml还是代码配置,这些配置最终都是被封装到RouteDefinition对象中,如下:
package org.springframework.cloud.gateway.route;
/**
* @author Spencer Gibb
*/
@Validated
public class RouteDefinition {
private String id;
@NotEmpty
@Valid
private List<PredicateDefinition> predicates = new ArrayList<>();
@Valid
private List<FilterDefinition> filters = new ArrayList<>();
@NotNull
private URI uri;
private Map<String, Object> metadata = new HashMap<>();
private int order = 0;
public RouteDefinition() {
}
一个RouteDefinition有个唯一的ID,如果不指定,就默认是UUID,多个RouteDefinition组成了gateway的路由系统。
所有路由信息在系统启动时就被加载装配好了,并存到了内存里,这点我们从 org.springframework.cloud.gateway.config.GatewayAutoConfiguration 类可以看出,如下:
/**
* @author Spencer Gibb
* @author Ziemowit Stolarczyk
*/
@Configuration(proxyBeanMethods = false)
@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 {
@Bean
public StringToZonedDateTimeConverter stringToZonedDateTimeConverter() {
return new StringToZonedDateTimeConverter();
}
@Bean
public RouteLocatorBuilder routeLocatorBuilder(
ConfigurableApplicationContext context) {
return new RouteLocatorBuilder(context);
}
//yml文件中配置的路由信息
@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
@Primary
@ConditionalOnMissingBean(name = "cachedCompositeRouteLocator")
// TODO: property to disable composite?
public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
return new CachingRouteLocator(
new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
}
@Bean
public RouteRefreshListener routeRefreshListener(
ApplicationEventPublisher publisher) {
return new RouteRefreshListener(publisher);
}
}
PropertiesRouteDefinitionLocator 就是 我们在yml文件中装配的路由信息,该类继承了RouteDefinitionLocator,RouteDefinitionLocator就是路由的装载器,里面只有一个方法,就是获取路由信息的。
RouteDefinitionLocator接口有多个实现类,分别对应不同方式配置的路由方式,

比较关键的几个如下:
- CachingRouteDefinitionLocator:为RouteDefinitionLocator类提供缓存功能;
- CompositeRouteDefinitionLocator:组合多种RouteDefinitionLocator实现;
- PropertiesRouteDefinitionLocator:从配置文件(例如 YML / properties 等)读取RouteDefinition;
- DiscoveryClientRouteDefinitionLocator:从注册中心(例如 Eureka、Consul、Nacos、Zookeeper等)读取RouteDefinition;
通过这几个实现类,再结合上面的AutoConfiguration里面的Primary信息,就知道加载配置信息的顺序。
PropertiesRouteDefinitionLocator-->|配置文件加载初始化| CompositeRouteDefinitionLocator
RouteDefinitionRepository-->|存储器中加载初始化| CompositeRouteDefinitionLocator
DiscoveryClientRouteDefinitionLocator-->|注册中心加载初始化| CompositeRouteDefinitionLocator