问题:
访问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.1: SimpleHandlerAdapter.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.2:FilteringWebHandler.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主要关注两个 特别的:LoadBalancerClientFilter,NettyRoutingFilter
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
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);
}));