GateWay路由源码分析
springgateway 简介
springcloud 提供了便于我们编写网关组件,分别是zuul和gateway;在zuul1的通信模型是BIO而zuul2的通信模型采用了NIO;spring gateway的IO模型使用的是NIO;但是从netflix发布zuul2后spring已经 开始 不集成zuul组件了。spring gateway的架构是基于WebFlux基础开发的。它依赖springboot2.x,spring5和netty
Spring GateWay请求转发流程
在spring MVC是通过handlermapping解析请求连接然后根据请求连接找到执行请求的controller类;而gateway采用同样的方式,用handlerMapping 堆请求连接进行解析匹配对应的Route,然后有对应的filter做对应的请求转发。整个流程用户请求先通过dispatchHandler找到对应的GateWayHandlerMapping ,再由GateWayHandlerMapping解析匹配对应的handler;handler处理完成后再经过filter链处理最终分发到proxied service。
转发请求解析
- 请求先有DispatcherHandler进行处理,DispatchHandler在IOC容器初始化时会在容器中所有实现HandlerMapping接口的实例放到handlerMappers属性中,DispatchHandler调用handler方法迭代handlerMappings中的handlerMapping。
- RoutePredicateHandlerMapping是其中一个实现了HandlerMapping接口的类,它负责处理基于路由的处理的mapping实现类;RoutePredicateHandlerMapping 根据请求URL找到对应的路由配置信息将route的配置信息存放到ServerWebExchange中然后返回实现了WebHandler接口的FilterWebHandler,FilterWebHandler是一个存放过滤器的handler。
- 最后DispatchHandler通过SimpleHandlerAdaptor适配器调用FilteringWebHandler的handle方法,FilteringWebHandler调用所有的过滤器,包括proxy filter,通过proxy filter请求被代理的服务;处理完毕后将response返回去。
HandlerMapping,RouteLocator,GlobalFilter,WebHandler
HandlerMapping
handler 继承关系图
AbstractHandlerMapping
HandlerMapping和Ordered接口主要定义了获取getHandler和当前handler的加载顺序。AbstractHandlerMapping 在getHandler封装了CORS处理,因为所有的handler都会涉及到CORS处理,抽象到AbstractHandlerMapping处理,再提供getHandlerInternal让子类实现具体的查找方法在这里插入代码片。
/**
*获取handler方法
**/
public Mono<Object> getHandler(ServerWebExchange exchange) {
return this.getHandlerInternal(exchange).map((handler) -> {
if (CorsUtils.isCorsRequest(exchange.getRequest())) {
CorsConfiguration configA = this.globalCorsConfigSource.getCorsConfiguration(exchange);
CorsConfiguration configB = this.getCorsConfiguration(handler, exchange);
CorsConfiguration config = configA != null ? configA.combine(configB) : configB;
if (!this.getCorsProcessor().process(config, exchange) || CorsUtils.isPreFlightRequest(exchange.getRequest())) {
return REQUEST_HANDLED_HANDLER;
}
}
return handler;
});
}
//抽象方法,让子类实现具体查找handler的
protected abstract Mono<?> getHandlerInternal(ServerWebExchange var1);
我们可以通过代码学习学习到如果所有的接口的实现类都需要在接口定义方法或者后执行一些共性操作,我们可以通过抽象类实现共性的操作,再通过定义抽象方法,让子类实现特有的实现。这种模式叫做模板模式。
RoutePredicateHandlerMapping
RoutePredicateHandlerMapping是处理获取handler。RoutePredicateHandlerMapping中的RouteLocator存储gateway启动时加载的路由对象信息。获取路由的时候,调用RoutePredicateHandlerMapping的getHandlerInternal方法,从routeLocator获取路由存放在WebServerExchange中,返回Filter。
private final RouteLocator routeLocator;
@override
public Mono<?> getHandlerExternal(ServerWebExchange exchange){
exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().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.