文章目录

  • RouteDefinition 定义
  • 服务发现构建RouteDefinition
  • 根据服务发现规则转发请求
  • 匹配 Route
  • Route 转发


RouteDefinition 定义

SpringCloudGateway内,路由转发规则被定义为RouteRoute通过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

spring cloud gateway 转发带域名 spring cloud gateway 路由转发原理_微服务

服务发现构建RouteDefinition

SpringCloudGateway会获取所有RouteDefinitionLocator的实现Bean,获取所有定义的RouteDefinition,因此我们可以实现自定义的RouteDefinitionLocator实现自定义的路由规则。

spring cloud gateway 转发带域名 spring cloud gateway 路由转发原理_微服务_02

接下来主要关注DiscoveryClientRouteDefinitionLocator,基于服务发现的路由定义方式。

下图为SpringCloudGateway根据服务发现创建的其中一个RouteDefinition内容。

spring cloud gateway 转发带域名 spring cloud gateway 路由转发原理_服务发现_03

  • 每一个RouteDefinition都有id唯一标识,格式为ReactiveCompositeDiscoveryClient_{微服务名}
  • predicates内容格式/{service-name}/**,表示为请求路径以微服务名为前缀的请求,都有当前Route处理。
  • filters表示/{service-name}/xxx的请求路径,通过filter转化为/xxx请求路径,重写请求路径。
  • uri表示Route转发的地址为lb://{service-name},之后配合负载均衡,调用实际的微服务地址。

spring cloud gateway 转发带域名 spring cloud gateway 路由转发原理_服务发现_04

根据服务发现规则转发请求

匹配 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,内部的urilb://开头的微服务地址,在LoadBalancerClientFilter内部会被根据负载均衡替换为实际的微服务地址,最后请求被转发到对应的微服务实例。

spring cloud gateway 转发带域名 spring cloud gateway 路由转发原理_List_05