Spring Cloud Gateway 执行流程分析

原创
2021/03/19 21:50
阅读数 1.5K

 

gateway工作流程:

1.匹配路由

2.构建过滤器

3.执行过滤器链

4.调用服务

 

spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,\
org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration

这里比较重要的两个类:GatewayLoadBalancerClientAutoConfiguration、GatewayAutoConfiguration

SPI中通过EnableAutoConfiguration导入了

GatewayLoadBalancerClientAutoConfiguration:

	@Bean
	@ConditionalOnBean(LoadBalancerClient.class)
	@ConditionalOnMissingBean(LoadBalancerClientFilter.class)
	public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client) {
		return new LoadBalancerClientFilter(client);
	}

这个类主要注册了一个Bean:LoadBalancerClientFilter,它实现了GlobalFilter,是一个全局过滤器(过滤链会用到)

 

GatewayAutoConfiguration

它是网关的核心配置类,其中有三个重要的Bean:

    RoutePredicateHandlerMapping:通过Route匹配处理器

    GatewayProperties: 配置文件相关类

    RouteDefinitionLocator:获得Route对象(记录路由信息)

 

请求最终会进入到org.springframework.web.reactive.DispatcherHandler#handle方法:

它传入了ServerWebExchange对象,它是对request的封装,相当于一个加强版的request

                Flux.fromIterable(this.handlerMappings)
				.concatMap(mapping -> mapping.getHandler(exchange)) // 获得过滤器
				.next()
				.switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION))
				.flatMap(handler -> invokeHandler(exchange, handler)) // 执行过滤器
				.flatMap(result -> handleResult(exchange, result))

获得过滤器

这里首先会遍历handlerMappings(它是请求和处理程序对象的集合),调用它的getHandler方法:

getHandler中实际调用的正是之前所注入的RoutePredicateHandlerMapping中getHandlerInternal方法,这个方法主要做了两件事:

		return lookupRoute(exchange) // 1.获得Route
				.flatMap((Function<Route, Mono<?>>) r -> {
					exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
					if (logger.isDebugEnabled()) {
						logger.debug("Mapping [" + getExchangeDesc(exchange) + "] to " + r);
					}

					exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);// 2.放入传入的request中
					return Mono.just(webHandler);
				}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
					exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
					if (logger.isTraceEnabled()) {
						logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]");
					}
				})));

lookupRoute逻辑:

                this.routeLocator
				.getRoutes() // 1.获得Route
				//individually filter routes so that filterWhen error delaying is not a problem
				.concatMap(route -> Mono
						.just(route)
						.filterWhen(r -> {
							// add the current route we are testing
                            // 2.放入request
							exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
							return r.getPredicate().apply(exchange);
						})
						//instead of immediately stopping main flux due to error, log and swallow it
						.doOnError(e -> logger.error("Error applying predicate for route: "+route.getId(), e))
						.onErrorResume(e -> Mono.empty())
				)

这里getRoutes()调用的正是之前所注入的RouteDefinitionLocator中的方法,主要做了两件事:

	public Flux<Route> getRoutes() {
		return this.routeDefinitionLocator.getRouteDefinitions() // 1.从配置文件,注册中心等地方获得RouteDefinition
				.map(this::convertToRoute)// 2.将Definition转换为Route,这里会构建lanjie器链给Route
				//TODO: error handling
				.map(route -> {
					if (logger.isDebugEnabled()) {
						logger.debug("RouteDefinition matched: " + route.getId());
					}
					return route;
				});
	}

执行过滤器

invokeHandler逻辑:

	private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
				if (handlerAdapter.supports(handler)) {
					return handlerAdapter.handle(exchange, handler);
				}
			}
		}
		return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
	}

可以看到,遍历handlerAdapters,通过handlerAdapter调用handle方法

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle:

	public Mono<Void> handle(ServerWebExchange exchange) {
		Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
		List<GatewayFilter> gatewayFilters = route.getFilters();// 获得过滤器集合

		List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
		combined.addAll(gatewayFilters); // 和全局过滤器合并
		//TODO: needed or cached?
		AnnotationAwareOrderComparator.sort(combined);

		if (logger.isDebugEnabled()) {
			logger.debug("Sorted gatewayFilterFactories: "+ combined);
		}

		return new DefaultGatewayFilterChain(combined).filter(exchange);// 构建lanjie器链,执行filter方法
	}

这里就会调用之前初始化过的LoadBalancerClientFilter了,其中核心的代码:

final ServiceInstance instance = choose(exchange);

 

	protected ServiceInstance choose(ServerWebExchange exchange) {
		return loadBalancer.choose(((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost());
	}

调用了choose方法,通过ribbon实现的逻辑去选择一个服务实例ServiceInstance。

	@Override
	public ServiceInstance choose(String serviceId) {
		Server server = getServer(serviceId);
		if (server == null) {
			return null;
		}
		return new RibbonServer(serviceId, server, isSecure(server, serviceId),
				serverIntrospector(serviceId).getMetadata(server));
	}

此处逻辑就属于ribbon了,就不写了

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部