开源网关现状:
目前java开源网关主要由zuul、SpringCloudGateway等两款,但是目前这两款网关都还需要根据自身的业务需求进行扩展。所以有不少公司公司对其二次开发,当然也有部分公司选择自研网关。大部分可能会基于原生netty来做,但是个人觉得基于原生netty去写花费时间以及难度都比较高,所以建议基于Spring WebFlux(基于netty开发)来做响应式网关。
如何基于SpringWebFlux代理请求:
其实做网关最核心的点是代理请求,如果代理到请求其他功能自然手到擒来,那么如何基于WebFlux来代理请求呢?有如下两个核心API需要扩展:
1.AbstractHandlerMapping
2.WebHandler
下面介绍SpringCloudGateway如何扩展这两个类的:
1.RoutePredicateHandlerMapping:
此类主要拦截到请求后交给FilteringWebHandler进行处理
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:
此类处理具体请求,同时执行整个Filter链,这也就是使用扩展了SpringCloudGateway中Filter执行的地方。
@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服务还会是难事吗?
近期评论