SpringCloudGateway原理——Gateway集成eureka服务发现转发请求

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

在这里插入图片描述

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

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值