如何基于SpringWebFlux打造高性能网关

开源网关现状:

目前java开源网关主要由zuul、SpringCloudGateway等两款,可是目前这两款网关都还须要根据自身的业务需求进行扩展。因此有很多公司公司对其二次开发,固然也有部分公司选择自研网关。大部分可能会基于原生netty来作,可是我的以为基于原生netty去写花费时间以及难度都比较高,因此建议基于Spring WebFlux(基于netty开发)来作响应式网关。java

如何基于SpringWebFlux代理请求:

其实作网关最核心的点是代理请求,若是代理到请求其余功能天然手到擒来,那么如何基于WebFlux来代理请求呢?有以下两个核心API须要扩展:web

1.AbstractHandlerMappingbash

2.WebHandlerapp

下面介绍SpringCloudGateway如何扩展这两个类的:ide

1.RoutePredicateHandlerMapping:ui

此类主要拦截到请求后交给FilteringWebHandler进行处理this

private final FilteringWebHandler webHandler;

private final RouteLocator routeLocator;

@Override
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
   if (this.managementPortType == DIFFERENT && this.managementPort != null
         && exchange.getRequest().getURI().getPort() == this.managementPort) {
      return Mono.empty();
   }
   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);
            }

            exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
            return Mono.just(webHandler);//这里交给FilteringWebHandler处理
         }).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
            exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
            if (logger.isTraceEnabled()) {
               logger.trace("No RouteDefinition found for ["
                     + getExchangeDesc(exchange) + "]");
            }
         })));
}
复制代码

2.FilteringWebHandler:spa

此类处理具体请求,同时执行整个Filter链,这也就是使用扩展了SpringCloudGateway中Filter执行的地方。debug

@Override
public Mono<Void> handle(ServerWebExchange exchange) {
	//各位能够在此处实现认证、限流、熔断、灰度等等功能
   Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
   List<GatewayFilter> gatewayFilters = route.getFilters();

   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);
   }

   return new DefaultGatewayFilterChain(combined).filter(exchange);
}
复制代码

最后

上述已经介绍了如何SpringCloudGateway如何实现请求代理,那么若是你想基于SpringWebFlux打造属于本身的网关就能够参照上述实现,这样网关支持SpringCloud中全部的注册中心、Dubbo、http服务还会是难事吗?代理

相关文章
相关标签/搜索