You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Webflux请求日志逻辑中getBody().doOnNext()调用次数不固定?

问题原因
  1. HTTP请求体在传输时可能被拆分为多个TCP数据包,WebFlux会将每个数据包封装为独立的DataBuffer对象,通过Flux<DataBuffer>依次发射,并非所有场景下都只会返回1个DataBuffer元素。你当前的代码将日志打印逻辑放在doOnNext中,每收到一个DataBuffer就会触发一次日志输出,自然会出现多条拆分的请求体日志。
  2. 现有代码存在隐藏bug:第一个DataBuffer处理完成后就关闭了ByteArrayOutputStream,后续DataBuffer写入时会触发IO异常,仅因为你捕获了异常才没有向上传播,但日志记录的内容也会不完整。
修复方案

你需要先把所有DataBuffer拼接为完整的请求体,等所有内容接收完毕后再打印日志,再将完整请求体传递给下游处理,同时要注意DataBuffer的内存释放,避免内存泄漏。修复后的代码参考如下:

@Override
public Flux<DataBuffer> getBody() {
    DataBufferFactory bufferFactory = getDelegate().bufferFactory();
    return DataBufferUtils.join(super.getBody())
            .flatMapMany(fullBuffer -> {
                // 读取完整请求体打日志
                try {
                    byte[] bodyBytes = new byte[fullBuffer.readableByteCount()];
                    fullBuffer.get(fullBuffer.readerIndex(), bodyBytes);
                    String body = new String(bodyBytes, StandardCharsets.UTF_8);
                    LOGGER.info("Request: method={}, uri={}, payload={}, audit={}", 
                            getDelegate().getMethod(),
                            getDelegate().getPath(), 
                            body, 
                            value("audit", true));
                    // 返回完整请求体给下游
                    return Flux.just(bufferFactory.wrap(bodyBytes));
                } finally {
                    // 释放原有的DataBuffer,避免内存泄漏
                    DataBufferUtils.release(fullBuffer);
                }
            })
            // 处理空请求体场景
            .switchIfEmpty(Flux.empty());
}

如果你的业务场景存在下游多次订阅请求体Flux的情况,可以在返回的Flux最后添加.cache()操作符,避免重复读取请求体导致的重复日志问题。

内容的提问来源于stack exchange,提问作者genki98

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 23:36:05