Spring Cloud Gateway 之网关处理器总体解析

举报
qingting-fly 发表于 2021/01/21 17:54:47 2021/01/21
【摘要】 网关处理器请求到达网关之后,会有各种Web处理器对请求进行匹配与处理,下图为Spring Cloud Gateway中主要涉及到的WebHandler:DispatcherHandler -> RoutePredicateHandlerMapping -> FilteringWebHandler -> DefaultGatewayFilterChain按照顺序,这一小节将会讲解前两个,负责对...

网关处理器

请求到达网关之后,会有各种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 WebHandlerApplicationContextAware {
 @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是一个定义了请求与处理器对象映射的接口,有多个实现类,如ControllerEndpointHandlerMappingRouterFunctionMapping。 

网关这里主要关注的是RoutePredicateHandlerMapping,该类继承了抽象类AbstractHandlerMapping#mapping.getHandler(exchange)方法就是定义在该抽象类中:

public abstract class AbstractHandlerMapping extends ApplicationObjectSupport implements HandlerMappingOrdered {
 @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) 

从上面的截图可以看出,上一步的结果返回的是FilteringWebHandlerWebHandler有其对应的适配器,这里对应的是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_ATTRRoutePredicateHandlerMapping的类名;然后顺序匹配请求对应的Route,RouteLocator接口用于获取在网关中定义的路由,并根据请求的信息,与路由定义的断言进行匹配(路由的定义也有优先级,按照优先级顺序匹配)。设置GATEWAY_ROUTE_ATTR 为匹配的 Route,并返回相应的handler。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。