Spring Cloud Gateway 之网关处理器总体解析
网关处理器
请求到达网关之后,会有各种Web处理器对请求进行匹配与处理,下图为Spring Cloud Gateway中主要涉及到的WebHandler:
DispatcherHandler -> RoutePredicateHandlerMapping -> FilteringWebHandler -> DefaultGatewayFilterChain
按照顺序,这一小节将会讲解前两个,负责对请求路由选择和定位。
请求的分发器
Spring Cloud Gateway 引入了Spring-webflux,DispatcherHandler
是Spring WebFlux 的访问入口,请求分发处理器。在之前的项目中,引入Spring MVC,而它的分发处理器是DispatcherServlet
。下面具体看一下网关收到请求后,如何匹配HandlerMapping
。
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
//不存在handlerMappings则报错
return Mono.error(HANDLER_NOT_FOUND_EXCEPTION);
}
return 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));
}
//...
}
DispatcherHandler
实现了WebHandler
接口,WebHandler
接口用于处理web请求。DispatcherHandler
的构造函数会初始化好HandlerMapping
。核心处理的方法#handle(ServerWebExchange exchange)
,HandlerMapping
是一个定义了请求与处理器对象映射的接口,有多个实现类,如ControllerEndpointHandlerMapping
,RouterFunctionMapping
。
网关这里主要关注的是RoutePredicateHandlerMapping
,该类继承了抽象类AbstractHandlerMapping
,#mapping.getHandler(exchange)
方法就是定义在该抽象类中:
public abstract class AbstractHandlerMapping extends ApplicationObjectSupport implements HandlerMapping, Ordered {
@Override
public Mono<Object> getHandler(ServerWebExchange exchange) {
return getHandlerInternal(exchange).map(handler -> {
...//cors相关的配置
return handler;
});
}
protected abstract Mono<?> getHandlerInternal(ServerWebExchange exchange);
}
可以看出,抽象类在handler映射中起到的作用是将公用功能的抽取,不是我们关注的重点,代码省略。具体的实现定义在HandlerMapping
中。
#mapping.getHandler
返回了相应的Web处理器,随后到达invokeHandler(exchange, handler)
从上面的截图可以看出,上一步的结果返回的是FilteringWebHandler
,WebHandler
有其对应的适配器,这里对应的是SimpleHandlerAdapter
,适配器类的实现较为简单,直接调用了对应的WebHandler
的处理方法。
路由断言的HandlerMapping
RoutePredicateHandlerMapping
用于匹配 Route,并返回处理 Route 的 FilteringWebHandler
。
public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
public RoutePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator) {
this.webHandler = webHandler;
this.routeLocator = routeLocator;
setOrder(1);
}
//....
}
RoutePredicateHandlerMapping
的构造函数接收两个参数:FilteringWebHandler
网关过滤器和RouteLocator
路由定位器。#setOrder(1)
用于设置该对象初始化的优先级,Spring Cloud Gateway 的 GatewayWebfluxEndpoint
提供的HTTP API不需要经过网关,它通过 RequestMappingHandlerMapping
进行请求匹配处理。RequestMappingHandlerMapping 的 order为0 ,需要排在RoutePredicateHandlerMapping
前面。所以RoutePredicateHandlerMapping
设置的order必须大于0。
@Override
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
//设置GATEWAY_HANDLER_MAPPER_ATTR 为 RoutePredicateHandlerMapping
exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName());
return lookupRoute(exchange)
.flatMap((Function<Route, Mono<?>>) r -> {
//设置 GATEWAY_ROUTE_ATTR 为匹配的 Route
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
return Mono.just(webHandler);
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
//logger
})));
}
//顺序匹配请求对应的Route
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
return this.routeLocator.getRoutes()
.filter(route -> route.getPredicate().test(exchange))
.next()
.map(route -> {
//校验 Route 的有效性
validateRoute(route, exchange);
return route;
});
}
如上为获取handler的方法,用于匹配请求的Route,并返回处理Route的FilteringWebHandler
。首先设置 GATEWAY_HANDLER_MAPPER_ATTR
为 RoutePredicateHandlerMapping
的类名;然后顺序匹配请求对应的Route,RouteLocator
接口用于获取在网关中定义的路由,并根据请求的信息,与路由定义的断言进行匹配(路由的定义也有优先级,按照优先级顺序匹配)。设置GATEWAY_ROUTE_ATTR
为匹配的 Route,并返回相应的handler。
- 点赞
- 收藏
- 关注作者
评论(0)