Java教程

Spring Cloud Gateway 请求报文获取 高性能实现方法

本文主要是介绍Spring Cloud Gateway 请求报文获取 高性能实现方法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

简介

本文使用的spring cloud版本:2020.0.1

关于Spring Cloud Gateway报文获取,网上写法较多参考ModifyRequestBodyGatewayFilterFactory,经过非严谨测试其性能下降剧烈。

本文同样参考Spring Cloud Gateway源码,只不过参考的是ReadBodyRoutePredicateFactory,经过非严谨测试该方式性能会下降20%-30%,性能相较上述方案有了巨大提升。

 

写法核心逻辑(直接仿写ReadBodyRoutePredicateFactory,定义一个Filter)

@Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//WebFilterChain GatewayFilterChain
        ServerHttpRequest currentHttpRequest = exchange.getRequest();
        if(logReqRespUtils.needGenerateSn(currentHttpRequest.getMethod())){
return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange,(serverHttpRequest) ->
                    ServerRequest
                            .create(exchange.mutate().request(serverHttpRequest).build(), messageReaders)
                            .bodyToMono(String.class)
                            .defaultIfEmpty("")
                            .doOnNext(objectValue -> {

                                //objectValue即为请求Body内容
                                
                            })
                            .flatMap(bodyString->{
                                if (serverHttpRequest == exchange.getRequest()) {
                                    return chain.filter(exchange);
                                }
                                //ServerWebExchangeUtils.cacheRequestBodyAndRequest中已经缓存了可重复读的request 并且request也已经转换成了可重复度的request
                                ServerHttpRequest cacheRequest = (ServerHttpRequest)exchange.getAttributes().get(ServerWebExchangeUtils.CACHED_SERVER_HTTP_REQUEST_DECORATOR_ATTR);
                                return chain.filter(exchange.mutate().request(cacheRequest).build());
                            })
            );
        }
        return chain.filter(exchange);
    }

 

 

简单分析

ReadBodyRoutePredicateFactory可用来对请求体内容进行判断。

如此其中一定会获取请求体。

该文件短短一百多行代码,很快就可以定位到其核心部分:

在完成request和requestBody的缓存之后,通过ServerHttpRequest创建了一个ServerRequest ,拿到请求体的字符串,之后进行判断。

 

 查看 ServerWebExchangeUtils相关代码,显然可见:

 

 

 获取了body(Flux<DataBuffer>),之后装饰了一个新的Request,在exchange中将dataBuffer(请求体)和装饰后的Request进行缓存。之后交由我们自定义的逻辑进行处理。

 

 

 上图的 decorate方法中有一处 用到了Netty的retainedSlice方法:

 

 大意就是创建了一个ByteBuf的副本,不过是同源的,改内容会彼此影响,操作索引不会彼此影响。因此可以重复读,不需要我们手动释放,最后交由Spring去释放掉。

这篇关于Spring Cloud Gateway 请求报文获取 高性能实现方法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!