gateway学习——转发的过程 源码解读(4)完

问题:

访问gateway的地址:localhost:8080/spring-nacos/user/info
是如何转发到 localhost:8081/spring-nacos/user/info 项目的

DispatcherHandler类就是gateway的请求入口,
(怎么知道这是入口,大概是:http请求——>netty线程模型,处理read事件——>然后调用DispatcherHandler.hanlder方法。这一块没去研究,百度到的)。

DispatcherHandler

先介绍一下这个类:
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
	//1: 实现了 ApplicationContextAware 接口,setApplicationContext(ApplicationContext applicationContext)方法,
	//2: 实现了WebHandler 接口,handle(ServerWebExchange exchange); 方法。
}

看下其实现该方法的逻辑:

1:setApplicationContext:

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) {
		//初始化策略
		initStrategies(applicationContext);
	}

	//这里初始化是给 属性handlerMappings ,handlerAdapters ,resultHandlers 赋值。
	protected void initStrategies(ApplicationContext context) {
		//这里是获取所有的 HandlerMapping 的Bean,
		//例如:RoutePredicateHandlerMapping, 是在:GatewayAutoConfiguration中 用@Bean注入
		//RequestMappingHandlerMapping, 是在:WebFluxAutoConfiguration中内部类:EnableWebFluxConfiguration的RequestMappingHandlerAdapter--->super.createRequestMappingHandlerAdapter();
		//RouterFunctionMapping, 与上面 RequestMappingHandlerMapping 实在同一个类中: @Bean RouterFunctionMapping
		//SimpleUrlHandlerMapping 是在 WebFluxConfigurationSupport 的 @Bean的HandlerMapping
		Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
				context, HandlerMapping.class, true, false);
		//排序
		ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
		AnnotationAwareOrderComparator.sort(mappings);
		//定义为 不可以修改
		this.handlerMappings = Collections.unmodifiableList(mappings);
		
		//获取 HandlerAdapter ,有三个。
		// RequestMappingHandlerAdapter 是在 WebFluxConfigurationSupport  的@Bean RequestMappingHandlerAdapter
		// HandlerFunctionAdapter 是在 WebFluxConfigurationSupport   的@Bean HandlerFunctionAdapter
		// SimpleHandlerAdapter 是在 WebFluxConfigurationSupport   的@Bean SimpleHandlerAdapter 
		Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
				context, HandlerAdapter.class, true, false);

		this.handlerAdapters = new ArrayList<>(adapterBeans.values());
		AnnotationAwareOrderComparator.sort(this.handlerAdapters);
		// 这里获取 :HandlerResultHandler, 都是在 WebFluxConfigurationSupport类中注入的Bean
		// ResponseEntityResultHandler 
		// ResponseBodyResultHandler
		// ViewResolutionResultHandler
		// ServerResponseResultHandler
		Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
				context, HandlerResultHandler.class, true, false);

		this.resultHandlers = new ArrayList<>(beans.values());
		AnnotationAwareOrderComparator.sort(this.resultHandlers);
	}

2:handle(ServerWebExchange exchange)方法

@Override
	public Mono<Void> handle(ServerWebExchange exchange) {
		if (this.handlerMappings == null) {
			return createNotFoundError();
		}
		//明天再将主流程,很重要
		return Flux.fromIterable(this.handlerMappings) //这里创建一个流
				.concatMap(mapping -> mapping.getHandler(exchange)) // 转换流后并 进行合并
				.next() //插入消息,不太懂
				.switchIfEmpty(createNotFoundError())
				.flatMap(handler -> invokeHandler(exchange, handler)) // flatMap转换。
				.flatMap(result -> handleResult(exchange, result));
	}

2.1 mapping.getHandler(exchange)方法

RoutePredicateHandlerMapping,RequestMappingHandlerMapping,RouterFunctionMapping,SimpleUrlHandlerMapping
这四个类都会进入AbstractHandlerMapping.getHandler(ServerWebExchange exchange)

public Mono<Object> getHandler(ServerWebExchange exchange) {
		return getHandlerInternal(exchange).map(handler -> {
			if (logger.isDebugEnabled()) {
				logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);
			}
			// 这里就是 cors的配置判断了,应该是判断是否满足跨域设置。
			ServerHttpRequest request = exchange.getRequest();
			if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
				CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(exchange) : null);
				CorsConfiguration handlerConfig = getCorsConfiguration(handler, exchange);
				config = (config != null ? config.combine(handlerConfig) : handlerConfig);
				if (!this.corsProcessor.process(config, exchange) || CorsUtils.isPreFlightRequest(request)) {
					return REQUEST_HANDLED_HANDLER;
				}
			}
			return handler;
		});
	}
2.1.1: getHandlerInternal(exchange)
	这个方法每个子类都有实现,以下分别开始讲。
2.1.1.1: RoutePredicateHandlerMapping.getHandlerInternal
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
		// don't handle requests on management port if set and different than server port
		if (this.managementPortType == DIFFERENT && this.managementPort != null
				&& exchange.getRequest().getURI().getPort() == this.managementPort) {
			return Mono.empty();
		}
		//这一步 设置属性 org.springframework.cloud.gateway.support.ServerWebExchangeUtils.gatewayHandlerMapper = RoutePredicateHandlerMapping
		exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName());
		//检查路由:方法逻辑下面详解
		return lookupRoute(exchange)
				// .log("route-predicate-handler-mapping", Level.FINER) //name this
				.flatMap((Function<Route, Mono<?>>) r -> {
					exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
					if (logger.isDebugEnabled()) {
						logger.debug(
								"Mapping [" + getExchangeDesc(exchange) + "] to " + r);
					}
					2.1.1.1.0:Route  put进去。
					exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
					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(exchange):检查路由:

protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
		// this.routeLocator是CachingRouteLocator,
		// getRoutes()= RouteDefinitionRouteLocator,
		// 这些都是@Bean注入的。
		// A: this.routeLocator.getRoutes()就会进入到: RouteDefinitionRouteLocator.getRoutes(),
		return this.routeLocator.getRoutes()
				// individually filter routes so that filterWhen error delaying is not a
				
				.concatMap(route -> Mono.just(route).filterWhen(r -> {
					// add the current route we are testing
					//添加属性,
					exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
					//这里就是根据请求和断言的条件匹配路由
					// E:点的 r.getPredicate().apply(exchange)。
				//这里的r.getPredicate() 就是B1点生成的 AsyncPredicate<ServerWebExchange>。然后执行其 apply方法:
				
					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()))
				.next()
				.map(route -> {
					if (logger.isDebugEnabled()) {
						logger.debug("Route matched: " + route.getId());
					}
					//验证路由,暂无实现逻辑
					validateRoute(route, exchange);
					return route;
				});
	}

A点的:this.routeLocator.getRoutes()讲解:
this.routeLocator是 RouteDefinitionRouteLocator的对象,

@Override
	public Flux<Route> getRoutes() {
		Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions()
				.map(this::convertToRoute);
	// this.routeDefinitionLocator.getRouteDefinitions()
	// this.routeDefinitionLocator是 CompositeRouteDefinitionLocator 对象,
	//所以 CompositeRouteDefinitionLocator.getRouteDefinitions(),复合类中会得到GatewayProperties.getRoutes(),
	//InMemoryRouteDefinitionRepository.getRoutes(),
	//CachingRouteDefinitionLocator.routeDefinitions,
	//DiscoveryClientRouteDefinitionLocator.serviceInstances.
	}
	
	this::convertToRoute讲解:

//RouteDefinition转化成 Route对象
private Route convertToRoute(RouteDefinition routeDefinition) {
		//B: 合并断言对象,
		AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
		//C: 获取gateway的过滤器
		List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);
		//D:生成Route对象
		return Route.async(routeDefinition).asyncPredicate(predicate)
				.replaceFilters(gatewayFilters).build();
	}
	

B: 合并断言对象
private AsyncPredicate<ServerWebExchange> combinePredicates(
			RouteDefinition routeDefinition) {
			//这里获取 RouteDefinition.predicates的值,
			//那这个属性从哪里赋值的呢?就是配置文件中的配置:
			//spring.cloud.gateway.routes.predicates属性
		List<PredicateDefinition> predicates = routeDefinition.getPredicates();
		//B1:检查第一个断言对象,大概意思就是 根据 断言的名字 去判断是否有其对应的路由断言工厂实现类RoutePredicateFactory,然后生成 AsyncPredicate对象,具体代码不列出来了,这个lookup里面返回的是: return factory.applyAsync(config) ,执行的就是ReadBodyRoutePredicateFactory类的applyAsync(Config config)方法,这个方法右返回了,new AsyncPredicate<ServerWebExchange>(){
	apply方法:
}
		AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition,
				predicates.get(0));
		//这里是检查剩下的断言对象
		for (PredicateDefinition andPredicate : predicates.subList(1,
				predicates.size())) {
			AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition,
					andPredicate);
			//这里的结构有点意思,个人理解是 (((left1,right1),right2),right3)
			predicate = predicate.and(found);
		}
		//比如有 predicate1,predicate2,predicate3,predicate4
		//生成的结构则是:
								(left            right)
					(left            right)
			(left       right)       
		(((predicate1,predicate2),predicate3),predicate4)
		return predicate;
	}

C: 获取gateway的过滤器

private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {
		List<GatewayFilter> filters = new ArrayList<>();
		//这里就是获取 默认的 spring.cloud.gateway.default-filters属性
		if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
			filters.addAll(loadGatewayFilters(DEFAULT_FILTERS,
					new ArrayList<>(this.gatewayProperties.getDefaultFilters())));
		}
		//这里是获取 spring.cloud.gateway.routes.filters的配置。
		if (!routeDefinition.getFilters().isEmpty()) {
			filters.addAll(loadGatewayFilters(routeDefinition.getId(),
					new ArrayList<>(routeDefinition.getFilters())));
		}
		//进行排序。
		AnnotationAwareOrderComparator.sort(filters);
		return filters;
	}

D:生成Route对象,这个对象带有 断言器与过滤器,id,uri,order,metadata等信息
return new Route(this.id, this.uri, this.order, predicate,
					this.gatewayFilters, this.metadata);


E:r.getPredicate().apply(exchange); 这里会执行到 ReadBodyRoutePredicateFactory.applyAsync()方法中返回的AsyncPredicate.apply()方法,
public Publisher<Boolean> apply(ServerWebExchange exchange) {
				Class inClass = config.getInClass();
				//精简代码,这里主要是执行
				//例如 predicate配置的是 -Path,这个config.predicate就会是PathRoutePredicateFactory.apply()方法中返回的GatewayPredicate.test()方法。
				config.predicate.test(cachedBody)
				
			}
	E1: 讲解这个Config对象的是怎么来的?
		是在 lookup(RouteDefinition route,PredicateDefinition predicate)中创建的
		//这里就会获取到相对应的 PathRoutePredicateFactory。
		RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName());
		Object config = this.configurationService.with(factory)
				.name(predicate.getName())
				.properties(predicate.getArgs())
				.eventFunction((bound, properties) -> new PredicateArgsEvent(
						RouteDefinitionRouteLocator.this, route.getId(), properties))
				.bind();
	E2:GatewayPredicate.test()方法中执行逻辑:主要是判断是否断言匹配,如果匹配就put属性URI_TEMPLATE_VARIABLES_ATTRIBUTE,并返回true.
	
	public boolean test(ServerWebExchange exchange) {
				//解析路径
				PathContainer path = parsePath(
						exchange.getRequest().getURI().getRawPath());
				
				//如果有 第一个匹配成功,
				Optional<PathPattern> optionalPathPattern = pathPatterns.stream()
						.filter(pattern -> pattern.matches(path)).findFirst();
				//如果匹配成功,
				if (optionalPathPattern.isPresent()) {
					PathPattern pathPattern = optionalPathPattern.get();
					traceMatch("Pattern", pathPattern.getPatternString(), path, true);
					PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(path);
					// 设置属性
					putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());
					return true;
				}
				else {
					traceMatch("Pattern", config.getPatterns(), path, false);
					return false;
				}
			}
2.1.1.2: RequestMappingHandlerMapping.

默认情况下:这个实现类 debug进来发现没做什么事。暂留存疑。

  @Override
	public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
		//删除属性:org.springframework.web.reactive.HandlerMapping.producibleMediaTypes
		exchange.getAttributes().remove(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
		// 调用父类的方法:
		return super.getHandlerInternal(exchange)
				.doOnTerminate(() -> ProducesRequestCondition.clearMediaTypesAttribute(exchange));
	}
父类的方法	
AbstractHandlerMethodMapping.getHandlerInternal

@Override
	public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
		//读锁
		this.mappingRegistry.acquireReadLock();
		try {
			HandlerMethod handlerMethod;
			try {
				//A:检查Handler的方法
				handlerMethod = lookupHandlerMethod(exchange);
			}
			catch (Exception ex) {
				return Mono.error(ex);
			}
			if (handlerMethod != null) {
				// B: 创建与解决Bean?
				handlerMethod = handlerMethod.createWithResolvedBean();
			}
			return Mono.justOrEmpty(handlerMethod);
		}
		finally {
			this.mappingRegistry.releaseReadLock();
		}
	}
	
//A:检查Handler的方法
protected HandlerMethod lookupHandlerMethod(ServerWebExchange exchange) throws Exception {
		List<Match> matches = new ArrayList<>();
		addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, exchange);
		//这里默认matches是会为空的,至于什么条件下会不会为空,后面在研究处理,这块的逻辑先留着
		if (!matches.isEmpty()) {
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(exchange));
			matches.sort(comparator);
			Match bestMatch = matches.get(0);
			if (matches.size() > 1) {
				if (logger.isTraceEnabled()) {
					logger.trace(exchange.getLogPrefix() + matches.size() + " matching mappings: " + matches);
				}
				if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
					return PREFLIGHT_AMBIGUOUS_MATCH;
				}
				Match secondBestMatch = matches.get(1);
				if (comparator.compare(bestMatch, secondBestMatch) == 0) {
					Method m1 = bestMatch.handlerMethod.getMethod();
					Method m2 = secondBestMatch.handlerMethod.getMethod();
					RequestPath path = exchange.getRequest().getPath();
					throw new IllegalStateException(
							"Ambiguous handler methods mapped for '" + path + "': {" + m1 + ", " + m2 + "}");
				}
			}
			handleMatch(bestMatch.mapping, bestMatch.handlerMethod, exchange);
			return bestMatch.handlerMethod;
		}
		else {
			//默认会走这里,debug模式 返回的是 null,
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), exchange);
		}
	}
2.1.1.3: RouterFunctionMapping.

默认情况下:这里也是null,没有任何逻辑

2.1.1.4: SimpleUrlHandlerMapping .

暂留:

2.2:handler -> invokeHandler(exchange, handler)

private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
		if (this.handlerAdapters != null) {
			//这里是在第1步的时候 就初始化了的handlerAdapters。
			for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
				//这里是有三个实现类的,SimpleHandlerAdapter是支持WebHandler的,而此时的 handler是 FilteringWebHandler
				if (handlerAdapter.supports(handler)) {
				    //所以这里会走2.2.1:SimpleHandlerAdapter.handle(ServerWebExchange exchange, Object handler)
				     
					return handlerAdapter.handle(exchange, handler);
				}
			}
		}
		return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
	}
2.2.1SimpleHandlerAdapter.handle(ServerWebExchange exchange, Object handler)

public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
		WebHandler webHandler = (WebHandler) handler;
			// 所以这里会走 2.2.2:FilteringWebHandler.handle(exchange) 
		Mono<Void> mono = webHandler.handle(exchange);
		return mono.then(Mono.empty());
}

2.2.2FilteringWebHandler.handle(exchange) 

	@Override
	public Mono<Void> handle(ServerWebExchange exchange) {
		//这里获取属性  Route是在 2.1.1.1.0 处 put进去的
		Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
		//获取到route的过滤器
		List<GatewayFilter> gatewayFilters = route.getFilters();
		// 获取全局的 过滤器 默认的全局过滤器。请看 2.2.0,代码中贴不了图片
		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);
		}
		 // 2.2.3: DefaultGatewayFilterChain.filter(exchange)调用链。
		return new DefaultGatewayFilterChain(combined).filter(exchange);
	}

2.2.3: DefaultGatewayFilterChain.filter(exchange)
	这个 GatewayFilterChain主要关注两个 特别的:LoadBalancerClientFilterNettyRoutingFilter
	LoadBalancerClientFilter 是在:GatewayLoadBalancerClientAutoConfiguration中注入的。
	NettyRoutingFilter 是在:GatewayAutoConfiguration中注入的。
	(1): 先看 GatewayLoadBalancerClientAutoConfiguration.filter(exchange)
	   精简代码
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
		String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);
		addOriginalRequestUrl(exchange, url);
		// 这里就是跟url的host去选取 服务机器了,这里就设计到服务发现与均衡算法了,具体在这里不介绍了,后续专门讲解。
		// 这里会进行 url:ip地址与端口的改变。
		final ServiceInstance instance = choose(exchange);
		URI uri = exchange.getRequest().getURI();
		// if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,
		// if the loadbalancer doesn't provide one.
		String overrideScheme = instance.isSecure() ? "https" : "http";
		if (schemePrefix != null) {
			overrideScheme = url.getScheme();
		}
		// 这里就是重新构建了一个URI,
		URI requestUrl = loadBalancer.reconstructURI(
				new DelegatingServiceInstance(instance, overrideScheme), uri);

		if (log.isTraceEnabled()) {
			log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
		}
		// 把最新的uri 绑定到GATEWAY_REQUEST_URL_ATTR属性中。
		exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
		// 继续下一个过滤器
		return chain.filter(exchange);
	}
	
	(2): NettyRoutingFilter.filter()
		 这里就贴代码了,就是 获取属性GATEWAY_REQUEST_URL_ATTR,然后进行http的请求发送

2.2.0

debug模式下 出来的全局过滤器

2.3:result -> handleResult(exchange, result)

这一块就暂时没什么好讲的了。跟2.1中getHandlerInternal(exchange) 差不多,也是判断 supports是否满足,然后返回结果。

return getResultHandler(result).handleResult(exchange, result)
				.checkpoint("Handler " + result.getHandler() + " [DispatcherHandler]")
				.onErrorResume(ex ->
						result.applyExceptionHandler(ex).flatMap(exResult -> {
							String text = "Exception handler " + exResult.getHandler() +
									", error=\"" + ex.getMessage() + "\" [DispatcherHandler]";
							return getResultHandler(exResult).handleResult(exchange, exResult).checkpoint(text);
						}));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值