最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Cloud Gateway 緩存區(qū)異常問題及解決方案

 更新時間:2024年06月13日 09:48:31   作者:小徐很努力  
最近在測試環(huán)境spring cloud gateway突然出現(xiàn)了異常,接下來通過本文給大家介紹Spring Cloud Gateway 緩存區(qū)異常問題解決方案,需要的朋友可以參考下

最近在測試環(huán)境spring cloud gateway突然出現(xiàn)了異常,在這里記錄一下,直接上干貨

1、問題背景

測試環(huán)境spring cloud gateway遇到以下異常

DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144(超出了緩沖區(qū)的最大字節(jié)數(shù)限制)

乍一看,問題很簡單啊,通過配置加大緩存區(qū)不就行了啊,于是就在application.yml加了以下配置

#將緩存區(qū)設(shè)置為2m
spring:
  codec:
    max-in-memory-size: 2MB

可是問題又出現(xiàn)了,通過調(diào)試發(fā)現(xiàn)配置的max-in-memory-size在程序啟動初始化確實(shí)是生效的。但是有業(yè)務(wù)調(diào)用的時候,此參數(shù)的接收值為null,maxInMemorySize還是讀取的默認(rèn)值(256K)。

那咋整,只能從源碼入手了。

2、分析源碼過程

通過異常日志,可以定位到異常位置

后來發(fā)現(xiàn)我們自定義的攔截器獲取body的信息是獲取方式,代碼如下

因?yàn)镠andlerStrategies.withDefaults() 是每次都需要重新創(chuàng)建對象,并非是spring注入的對象,所以每次獲取的都是默認(rèn)值,導(dǎo)致配置不生效。

3、解決辦法

在我們自定的攔截器中注入ServerCodecConfigurer類,通過該類獲取配置。這樣獲取到的就是我們在application.yml中配置的緩存區(qū)配置的字節(jié)數(shù)限制了。

具體代碼:

@Component
@Slf4j
public class RequestFilter implements GlobalFilter, Ordered {
    @Override
    public int getOrder() {
        return OrderedConstant.HIGHEST_PRECEDENCE;
    }
    //手動注入ServerCodecConfigurer
    @Autowired
    ServerCodecConfigurer codecConfigurer;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        long startTime = System.currentTimeMillis();
        try {
            final Log logDTO = new Log();
            ServerHttpRequest request = exchange.getRequest();
            // 設(shè)置X-Request-Id
            AtomicReference<String> requestId = new AtomicReference<>(GenerateIdUtils.requestIdWithUUID());
            Consumer<HttpHeaders> httpHeadersConsumer = httpHeaders -> {
                String headerRequestId = request.getHeaders().getFirst(HeaderConstant.REQUEST_ID);
                if (!Strings.isNullOrEmpty(headerRequestId)) {
                    requestId.set(headerRequestId);
                }
                logDTO.setRequestId(requestId.get());
                httpHeaders.set(HeaderConstant.REQUEST_ID, requestId.get());
                httpHeaders.set(HeaderConstant.START_TIME_KEY, String.valueOf(startTime));
            };
            // codecConfigurer.getReaders()獲取pplication.yml中配置的緩存區(qū)配置的字節(jié)數(shù)
            ServerRequest serverRequest = ServerRequest.create(exchange,
                    codecConfigurer.getReaders());
            URI requestUri = request.getURI();
            String uriQuery = requestUri.getQuery();
            String url = requestUri.getPath() + (!Strings.isNullOrEmpty(uriQuery) ? "?" + uriQuery : "");
            HttpHeaders headers = request.getHeaders();
            MediaType mediaType = headers.getContentType();
            String method = request.getMethodValue().toUpperCase();
            // 原始請求體
            final AtomicReference<String> requestBody = new AtomicReference<>();
            final AtomicBoolean newBody = new AtomicBoolean(false);
            if (mediaType != null && LogHelper.isUploadFile(mediaType)) {
                requestBody.set("上傳文件");
            } else {
                if (method.equals("GET")) {
                    if (!Strings.isNullOrEmpty(uriQuery)) {
                        requestBody.set(uriQuery);
                    }
                } else {
                    newBody.set(true);
                }
            }
            logDTO.setLevel(Log.LEVEL.INFO);
            logDTO.setRequestUrl(url);
            logDTO.setRequestBody(requestBody.get());
            logDTO.setRequestMethod(method);
            logDTO.setIp(IpUtils.getClientIp(request));
            ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate().headers(httpHeadersConsumer).build();
            ServerWebExchange build = exchange.mutate().request(serverHttpRequest).build();
            return build.getSession().flatMap(webSession -> {
                logDTO.setSessionId(webSession.getId());
                if (newBody.get() && headers.getContentLength() > 0) {
                    Mono<String> bodyToMono = serverRequest.bodyToMono(String.class);
                    return bodyToMono.flatMap(reqBody -> {
                        logDTO.setRequestBody(reqBody);
                        // 重寫原始請求
                        ServerHttpRequestDecorator requestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
                            @Override
                            public Flux<DataBuffer> getBody() {
                                NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
                                DataBuffer bodyDataBuffer = nettyDataBufferFactory.wrap(reqBody.getBytes());
                                return Flux.just(bodyDataBuffer);
                            }
                        };
                        return chain.filter(exchange.mutate()
                                .request(requestDecorator)
                                .build()).then(LogHelper.doRecord(logDTO));
                    });
                } else {
                    return chain.filter(exchange).then(LogHelper.doRecord(logDTO));
                }
            });
        } catch (Exception e) {
            log.error("請求日志打印出現(xiàn)異常", e);
            return chain.filter(exchange);
        }
    }
}

到此這篇關(guān)于Spring Cloud Gateway 緩存區(qū)異常的文章就介紹到這了,更多相關(guān)Spring Cloud Gateway 緩存區(qū)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

当雄县| 基隆市| 肥西县| 鄯善县| 舞钢市| 太湖县| 正安县| 恭城| 江山市| 贵州省| 门源| 游戏| 阜康市| 贡觉县| 鸡东县| 多伦县| 交城县| 外汇| 武宣县| 漳平市| 额尔古纳市| 吉安县| 元朗区| 南召县| 昭苏县| 西盟| 孝昌县| 曲麻莱县| 城口县| 内丘县| 万年县| 山阴县| 格尔木市| 周宁县| 杭锦后旗| 雷波县| 同仁县| 顺平县| 宁城县| 富顺县| 纳雍县|