基本组件
路由定位器(RouteDefinitionLocator )
RouteDefinitionLocator 负责读取路由配置(RouteDefinition
),Gateway实现了多种Locator。
public interface RouteDefinitionLocator {
Flux<RouteDefinition> getRouteDefinitions();
}
- PropertiesRouteDefinitionLocator
从配置文件( 例如,YML / Properties 等 ) 读取
- RouteDefinitionRepository
从存储器( 例如,内存 / Redis / MySQL 等 )读取。
- DiscoveryClientRouteDefinitionLocator
从注册中心( 例如,Eureka / Consul / Zookeeper / Etcd 等 )读取。
- CompositeRouteDefinitionLocator
组合多种 RouteDefinitionLocator 的实现,为 RouteDefinitionRouteLocator 提供统一入口。
- CachingRouteDefinitionLocator
已经被 CachingRouteLocator 取代。
路由定义(RouteDefinition)
@Validated
public class RouteDefinition {
@NotEmpty
private String id = UUID.randomUUID().toString();
@NotEmpty
@Valid
private List<PredicateDefinition> predicates = new ArrayList<>();
@Valid
private List<FilterDefinition> filters = new ArrayList<>();
@NotNull
private URI uri;
private int order = 0;
}
id
属性,ID 编号,唯一。predicates
属性,谓语定义数组。请求通过predicates
判断是否匹配。在 Route 里,PredicateDefinition 转换成 Predicate 。filters
属性,过滤器定义数组。在 Route 里,FilterDefinition 转换成 GatewayFilter 。uri
属性,路由向的 URI 。order
属性,顺序。当请求匹配到多个路由时,使用顺序小的。
RouteDefinition 提供 text
字符串创建对象(yaml配置中属性值),格式为:
${id}=${uri},${predicates[0]},${predicates[1]}...${predicates[n]}
public RouteDefinition(String text) ;
PredicateDefinition
@Validated
public class PredicateDefinition {
/**
* 谓语定义名字,通过 name 对应到 org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory 的实现类
*/
@NotNull
private String name;
/**
* 参数数组
*/
private Map<String, String> args = new LinkedHashMap<>();
}
提供了构造函数:
/**
* 根据 text 创建 PredicateDefinition
*
* @param text 格式 ${name}=${args[0]},${args[1]}...${args[n]}
* 例如 Host=iocoder.cn
*/
public PredicateDefinition(String text);
FilterDefinition
@Validated
public class FilterDefinition {
/**
* 过滤器定义名字。通过 name 对应到 org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory 的实现类
*/
@NotNull
private String name;
/**
* 参数数组
*/
private Map<String, String> args = new LinkedHashMap<>();
}
提供了构造函数:
/**
* 根据 text 创建 FilterDefinition
*
* @param text 格式 ${name}=${args[0]},${args[1]}...${args[n]}
* 例如 AddRequestParameter=foo, bar
*/
public FilterDefinition(String text);
CompositeRouteDefinitionLocator
组合多种 RouteDefinitionLocator 的实现,为 RouteDefinitionRouteLocator 提供统一入口
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return this.delegates.flatMap(RouteDefinitionLocator::getRouteDefinitions)
.flatMap(routeDefinition -> {
if (routeDefinition.getId() == null) {
return randomId().map(id -> {
routeDefinition.setId(id);
if (log.isDebugEnabled()) {
log.debug(
"Id set on route definition: " + routeDefinition);
}
return routeDefinition;
});
}
return Mono.just(routeDefinition);
});
}
路由定位器 (RouteLocator)
- RouteLocator 可以直接自定义路由(
org.springframework.cloud.gateway.route.Route
) ,也可以通过 RouteDefinitionRouteLocator 获取 RouteDefinition ,并转换成 Route 。 - RoutePredicateHandlerMapping 使用 RouteLocator 获得 Route 信息。
Route
Route与RouteDefinition结构相似。同时实现了Order接口。
public class Route implements Ordered {
/**
* 路由编号
*/
private final String id;
/**
* 路由向的 URI
*/
private final URI uri;
/**
* 顺序
*/
private final int order;
/**
* 谓语数组
*/
private final Predicate<ServerWebExchange> predicate;
/**
* 过滤器数组
*/
private final List<GatewayFilter> gatewayFilters;
}
Route 内置 Builder 类,根据RouteDefinition 构造对象。predicate
/ gatewayFilters
属性,需要调用 Builder 相关方法进行设置
public static Builder builder(RouteDefinition routeDefinition) {
// @formatter:off
return new Builder().id(routeDefinition.getId())
.uri(routeDefinition.getUri())
.order(routeDefinition.getOrder())
.metadata(routeDefinition.getMetadata());
// @formatter:on
}
RouteDefinitionLocator解析
PropertiesRouteDefinitionLocator
从GatewayProperties 中获取路由信息。
public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator {
private final GatewayProperties properties;
public PropertiesRouteDefinitionLocator(GatewayProperties properties) {
this.properties = properties;
}
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return Flux.fromIterable(this.properties.getRoutes());
}
}
GatewayProperties
GatewayProperties
,从配置文件读取 :
- 路由配置
通过 spring.cloud.gateway.routes
配置
- 默认过滤器配置。当 RouteDefinition => Route 时,会将过滤器配置添加到每个 Route 。
通过 spring.cloud.gateway.default-filters
配置
@ConfigurationProperties("spring.cloud.gateway")
@Validated
public class GatewayProperties {
/**
* List of Routes.
*/
@NotNull
@Valid
private List<RouteDefinition> routes = new ArrayList<>();
/**
* List of filter definitions that are applied to every route.
*/
private List<FilterDefinition> defaultFilters = new ArrayList<>();
}
RouteDefinitionRepository
public interface RouteDefinitionRepository
extends RouteDefinitionLocator, RouteDefinitionWriter {
}
类继承关系如下:
RouteDefinitionWriter
RouteDefinitionWriter
,路由配置写入接口。该接口定义了保存与删除两个方法
public interface RouteDefinitionWriter {
/**
* 保存路由配置
*
* @param route 路由配置
* @return Mono<Void>
*/
Mono<Void> save(Mono<RouteDefinition> route);
/**
* 删除路由配置
*
* @param routeId 路由编号
* @return Mono<Void>
*/
Mono<Void> delete(Mono<String> routeId);
}
InMemoryRouteDefinitionRepository
基于内存为存储器的 RouteDefinitionLocator
public class InMemoryRouteDefinitionRepository implements RouteDefinitionRepository {
private final Map<String, RouteDefinition> routes = synchronizedMap(
new LinkedHashMap<String, RouteDefinition>());
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return Flux.fromIterable(routes.values());
}
}
路由信息构造:
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap(r -> {
if (StringUtils.isEmpty(r.getId())) {
return Mono.error(new IllegalArgumentException("id may not be empty"));
}
routes.put(r.getId(), r);
return Mono.empty();
});
}
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap(id -> {
if (routes.containsKey(id)) {
routes.remove(id);
return Mono.empty();
}
return Mono.defer(() -> Mono.error(
new NotFoundException("RouteDefinition not found: " + routeId)));
});
}
自定义RouteDefinitionRepository
可以自定义RouteDefinitionRepository,如果没有自定义,才使用内存存储。
// GatewayAutoConfiguration.java
@Bean
@ConditionalOnMissingBean(RouteDefinitionRepository.class)
public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
return new InMemoryRouteDefinitionRepository();
}
DiscoveryClientRouteDefinitionLocator
DiscoveryClientRouteDefinitionLocator 通过调用 org.springframework.cloud.client.discovery.DiscoveryClient
获取注册在注册中心的服务列表,生成对应的 RouteDefinition 数组。
public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLocator {
private final DiscoveryLocatorProperties properties;
private final String routeIdPrefix;
private final SimpleEvaluationContext evalCtxt;
private Flux<List<ServiceInstance>> serviceInstances;
}
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
SpelExpressionParser parser = new SpelExpressionParser();
Expression includeExpr = parser
.parseExpression(properties.getIncludeExpression());
Expression urlExpr = parser.parseExpression(properties.getUrlExpression());
//构造服务实例是否可用predicate。
Predicate<ServiceInstance> includePredicate;
if (properties.getIncludeExpression() == null
|| "true".equalsIgnoreCase(properties.getIncludeExpression())) {
includePredicate = instance -> true;
}
else {
includePredicate = instance -> {
Boolean include = includeExpr.getValue(evalCtxt, instance, Boolean.class);
if (include == null) {
return false;
}
return include;
};
}
return serviceInstances.filter(instances -> !instances.isEmpty())
//返回可用实例
.map(instances -> instances.get(0)).filter(includePredicate)
.map(instance -> {
//构建definition
RouteDefinition routeDefinition = buildRouteDefinition(urlExpr,
instance);
final ServiceInstance instanceForEval = new DelegatingServiceInstance(
instance, properties);
//拷贝PredicateDefinition
for (PredicateDefinition original : this.properties.getPredicates()) {
PredicateDefinition predicate = new PredicateDefinition();
predicate.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs()
.entrySet()) {
//计算表达式值。
String value = getValueFromExpr(evalCtxt, parser,
instanceForEval, entry);
predicate.addArg(entry.getKey(), value);
}
routeDefinition.getPredicates().add(predicate);
}
//拷贝FilterDefinition
for (FilterDefinition original : this.properties.getFilters()) {
FilterDefinition filter = new FilterDefinition();
filter.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs()
.entrySet()) {
//计算表达式值。
String value = getValueFromExpr(evalCtxt, parser,
instanceForEval, entry);
filter.addArg(entry.getKey(), value);
}
routeDefinition.getFilters().add(filter);
}
return routeDefinition;
});
}
RouteLocator解析
RouteLocator
路由定位器接口,定义获得路由数组的方法
public interface RouteLocator {
Flux<Route> getRoutes();
}
CompositeRouteLocator
组合多种 RouteLocator 的实现类,为 RoutePredicateHandlerMapping 提供统一入口访问路由
public class CompositeRouteLocator implements RouteLocator {
private final Flux<RouteLocator> delegates;
public CompositeRouteLocator(Flux<RouteLocator> delegates) {
this.delegates = delegates;
}
@Override
public Flux<Route> getRoutes() {
return this.delegates.flatMap(RouteLocator::getRoutes);
}
}
CachingRouteLocator
CachingRouteLocator
,缓存路由的 RouteLocator 实现类。RoutePredicateHandlerMapping 调用 CachingRouteLocator 的 RouteLocator#getRoutes()
方法,获取路由。
public class CachingRouteLocator
implements Ordered, RouteLocator, ApplicationListener<RefreshRoutesEvent> {
private static final String CACHE_KEY = "routes";
private final RouteLocator delegate;
private final Flux<Route> routes;
private final Map<String, List> cache = new ConcurrentHashMap<>();
public CachingRouteLocator(RouteLocator delegate) {
this.delegate = delegate;
routes = CacheFlux.lookup(cache, CACHE_KEY, Route.class)
.onCacheMissResume(this::fetch);
}
}
RouteDefinitionRouteLocator
RouteDefinitionRouteLocator
,基于 RouteDefinitionLocator 的 RouteLocator 实现类。RouteDefinitionRouteLocator 从 RouteDefinitionLocator 获取 RouteDefinition ,转换成 Route
public class RouteDefinitionRouteLocator
implements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware {
/**
* Default filters name.
*/
public static final String DEFAULT_FILTERS = "defaultFilters";
protected final Log logger = LogFactory.getLog(getClass());
private final RouteDefinitionLocator routeDefinitionLocator;
private final ConfigurationService configurationService;
private final Map<String, RoutePredicateFactory> predicates = new LinkedHashMap<>();
private final Map<String, GatewayFilterFactory> gatewayFilterFactories = new HashMap<>();
private final GatewayProperties gatewayProperties;
}
构造函数
public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator,
List<RoutePredicateFactory> predicates,
List<GatewayFilterFactory> gatewayFilterFactories,
GatewayProperties gatewayProperties,
ConfigurationService configurationService) {
this.routeDefinitionLocator = routeDefinitionLocator;
this.configurationService = configurationService;
initFactories(predicates);
gatewayFilterFactories.forEach(
factory -> this.gatewayFilterFactories.put(factory.name(), factory));
this.gatewayProperties = gatewayProperties;
}
获得 Route
@Override
public Flux<Route> getRoutes() {
//routeDefinitionLocator获取RouteDefinitions,转换成Route
Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions()
.map(this::convertToRoute);
//错误是否抛出异常
if (!gatewayProperties.isFailOnRouteDefinitionError()) {
// instead of letting error bubble up, continue
routes = routes.onErrorContinue((error, obj) -> {
if (logger.isWarnEnabled()) {
logger.warn("RouteDefinition id " + ((RouteDefinition) obj).getId()
+ " will be ignored. Definition has invalid configs, "
+ error.getMessage());
}
});
}
return routes.map(route -> {
if (logger.isDebugEnabled()) {
logger.debug("RouteDefinition matched: " + route.getId());
}
return route;
});
}
//合并predicate,合并filters,构造一个route。
private Route convertToRoute(RouteDefinition routeDefinition) {
AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);
return Route.async(routeDefinition).asyncPredicate(predicate)
.replaceFilters(gatewayFilters).build();
}
自定义 RouteLocator
RouteLocatorBuilder用于自定义RouteLocator
public class RouteLocatorBuilder {
public Builder routes() {
return new Builder(context);
}
}
public static class Builder {
private List<Route.AsyncBuilder> routes = new ArrayList<>();
private ConfigurableApplicationContext context;
public Builder(ConfigurableApplicationContext context) {
this.context = context;
}
}
- RouteSpec:route builder。
- UriSpec:可以添加一个Uri
- PredicateSpec:可以应用到一个Uri的Predicate。
- BooleanOpSpec:逻辑操作Predicate。
- GatewayFilterSpec:GatewayFilter