系列文章
- 01-基本特性及核心概念
- 02-初始化解析之Route、Predicate、Filter的构建原理
- 03-RouteDefinitionLocator、RouteLocator解析
- 04-路由匹配RoutePredicateHandlerMapping
- 06-内置Predicate
- 07-过滤器解析之GlobalFilter
- 08-过滤器-GatewayFilter
- 09-结合注册中心实现动态路由
- 10-自定义Predicate实现黑名单
- 11-扩展RouteDefinitionRepository实现基于Redis的动态路由
创作不易,如果对您有帮助,麻烦辛苦下小手点个关注,有任何问题都可以私信交流哈。
祝您虎年虎虎生威。
Spring Cloud Gateway源码解析-02-初始化解析之Route、Predicate、Filter的构建原理文章我们了解了Route、Predicate、Filter是如何根据我们的配置创建的,这篇文章我们来继续了解SCG是如何处理我们的请求的。
首先掏出来我们的祖传图,很关键。
SCG是基于webflux的,webflux和springweb-mvc类似,通过HandlerMapping来接收处理请求。
通过上图可以看到Client请求首先会到Gateway HanderMapping,那可以猜到这个HandlerMapping一定是webflux的HandlerMaping的实现类,这个GatewayHandlerMapping就是RoutePredicateHandlerMapping
。
那RoutePredicateHandlerMapping
是如何接收并处理我们的请求的呢?
由来
RoutePredicateHandlerMapping
也是在GatewayAutoConfiguration
中进行装配的
/**
*
* @param webHandler 上边装配的FilteringWebHandler
* @param routeLocator 上边装配的CachingRouteLocator
*/
@Bean
public RoutePredicateHandlerMapping routePredicateHandlerMapping(
FilteringWebHandler webHandler, RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties, Environment environment) {
return new RoutePredicateHandlerMapping(webHandler, routeLocator,
globalCorsProperties, environment);
}
在springmvc中有一个核心类DispatcherServlet
,而对应webflux有一个核心类DispatcherHandler
同是请求的入口。从网上找到了一张更加清晰的流程图
DispatcherHander的#handler
方法用来匹配不同的handlerMapping来处理请求
@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())
//根据获取到的handler进行处理
.flatMap(handler -> invokeHandler(exchange, handler))
.flatMap(result -> handleResult(exchange, result));
}
通过debug可以看到我们的RoutePredicateHandlerMapping
就在其中
public interface HandlerMapping {
Mono<Object> getHandler(ServerWebExchange exchange);
}
在AbstractHandlerMapping
中实现了HandlerMapping
的handler方法
public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
implements HandlerMapping, Ordered, BeanNameAware {
@Override
public Mono<Object> getHandler(ServerWebExchange exchange) {
//调用子类(RoutePredicateHandlerMapping)实现获取handler
return getHandlerInternal(exchange).map(handler -> {
if (logger.isDebugEnabled()) {
logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);
}
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;
});
}
protected abstract Mono<?> getHandlerInternal(ServerWebExchange exchange);
}
SCG的RoutePredicateHandlerMapping
继承了AbstractHandlerMapping
实现了getHandlerInternal
方法
此方法将我们的路由信息放入了上下文中,并返回了FilteringWebHandler
,即FilteringWebHandler
后边的文章会讲解。
@Override
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();
}
exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName());
//这里可以看到调用了#lookupRoute去查找路由
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);
}
//将路由信息放入上下文中
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
//返回webHandler,即FilteringWebHandler
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
方法是用来查找真正的路由信息
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
return this.routeLocator.getRoutes()
// 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
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
//根据断言获取到真正的Route
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()))
// .defaultIfEmpty() put a static Route not found
// or .switchIfEmpty()
// .switchIfEmpty(Mono.<Route>empty().log("noroute"))
.next()
// TODO: error handling
.map(route -> {
if (logger.isDebugEnabled()) {
logger.debug("Route matched: " + route.getId());
}
//校验方法并没有实现,可以自己继承实现
validateRoute(route, exchange);
return route;
});
}
至此,就获取到了SCG处理的handler和Route信息,今天太晚了就到这里了,后边解析如何进行处理的以及SCG的Filter是如何作用的。