文章目录
- RouteDefinition 定义
- 服务发现构建RouteDefinition
- 根据服务发现规则转发请求
- 匹配 Route
- Route 转发
RouteDefinition 定义
在SpringCloudGateway
内,路由转发规则被定义为Route
,Route
通过RouteDefinitionRouteLocator#getRoutes
获取。
在RouteDefinitionRouteLocator
内先获取RouteDefinition
,即Route
的定义。RouteDefinition
通过RouteDefinitionLocator
获取。后者有多种实现,包括基于配置文件的实现PropertiesRouteDefinitionLocator
,基于服务发现的实现DiscoveryClientRouteDefinitionLocator
等。
RouteDefinition
数据结构
public class RouteDefinition {
@NotEmpty
@Valid
private List<PredicateDefinition> predicates = new ArrayList<>();
@Valid
private List<FilterDefinition> filters = new ArrayList<>();
@NotNull
private URI uri;
}
-
predicates
表示能够让当前Route
处理的请求,只有请求能够满足Route
所有的predicates
时,才被当前Route
接受。 -
filters
处理当前Route
接受的请求。 -
uri
路由地址。(最终请求使用的地址不一定是Route
内定义的uri
)
服务发现构建RouteDefinition
SpringCloudGateway
会获取所有RouteDefinitionLocator
的实现Bean
,获取所有定义的RouteDefinition
,因此我们可以实现自定义的RouteDefinitionLocator
实现自定义的路由规则。
接下来主要关注DiscoveryClientRouteDefinitionLocator
,基于服务发现的路由定义方式。
下图为SpringCloudGateway
根据服务发现创建的其中一个RouteDefinition
内容。
- 每一个
RouteDefinition
都有id
唯一标识,格式为ReactiveCompositeDiscoveryClient_{微服务名}
。 -
predicates
内容格式/{service-name}/**
,表示为请求路径以微服务名为前缀的请求,都有当前Route
处理。 -
filters
表示/{service-name}/xxx
的请求路径,通过filter
转化为/xxx
请求路径,重写请求路径。 -
uri
表示Route
转发的地址为lb://{service-name}
,之后配合负载均衡,调用实际的微服务地址。
根据服务发现规则转发请求
匹配 Route
SpringCloudGateway
收到外部请求后,根据route
请求的微服务名决定由哪个route
规则处理。
具体如何选择Route
方法见RoutePredicateHandlerMapping#getHandlerInternal
。
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
...
exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName());
return lookupRoute(exchange)
.flatMap((Function<Route, Mono<?>>) r -> {
...
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
...
})));
}
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
return this.routeLocator.getRoutes()
.concatMap(route -> Mono.just(route).filterWhen(r -> {
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
return r.getPredicate().apply(exchange);
})
.doOnError(e -> logger.error(
"Error applying predicate for route: " + route.getId(),
e))
.onErrorResume(e -> Mono.empty()))
.next()
.map(route -> {
...
validateRoute(route, exchange);
return route;
});
}
getHandlerInternal
根据请求信息查询对应的Route
,查询Route
逻辑都在lookupRoute
方法内。通过RouteDefinitionRouteLocator
获取所有的Route
,按照Route
内部的Predicates
匹配。
符合条件的第一个Route
被作为匹配成功的Route
返回。
Route 转发
通过服务发现获取到的Route
,内部的uri
为lb://
开头的微服务地址,在LoadBalancerClientFilter
内部会被根据负载均衡替换为实际的微服务地址,最后请求被转发到对应的微服务实例。