如何基於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服務還會是難事嗎?代理

相關文章
相關標籤/搜索