DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

WebClient 收到 200 后读取失败,检查 DataBufferLimitException

HTTP成功状态与正文聚合成功分开验收,检查默认codec容量和实际client,按响应与并发预算调整有界上限。

WebClient 已经收到 200 OK,调用 bodyToMono(String.class) 读取正文时仍失败,异常链里出现 DataBufferLimitException: Exceeded limit on max bytes to buffer。这时先查响应聚合上限:HTTP 状态成功只说明收到成功状态,正文尚未必读完或解码成功。

Spring WebFlux 默认编解码器的内存缓冲限制通常为 256KB。用 bodyToMono(String.class) 把一份大响应聚合成字符串时,可能超过这个限制。实际项目若配置过 codec 或使用自定义解码器,应以那份实例的配置为准。

从最早的异常确认是聚合超限

沿异常链看 DataBufferLimitException,记下报错中的字节上限,以及具体请求和读取方式。日志中的 64 字节之类数值可能是人为设定的阈值,不是框架默认值。

同时确认真正发请求的 WebClient 实例。项目可能有多个 Bean、不同的构建路径,或者某个调用处另建了 client。只修改一份未被使用的配置,错误会继续存在。

历史上的 Spring Boot 2.3.5、Reactor Netty 0.9.13 组合还可能在超限之后出现 IllegalReferenceCountException: refCnt: 0, decrement: 1。这类引用计数错误与导致读取失败的聚合限制要分别核对,不能把任意引用计数异常都归为响应太大。连接超时、连接中断和服务端错误状态也应按各自的异常处理。

对有界响应调整特定 client

若业务确实需要把整份正文读取为字符串,并且响应大小有可接受的边界,可以增加这个 client 的默认 codec 上限。下面是已有方法中的配置片段,originalClient 指项目已配置好的 org.springframework.web.reactive.function.client.WebClient:

WebClient largeResponseClient = originalClient.mutate()
    .codecs(configurer -> configurer.defaultCodecs()
        .maxInMemorySize(2 * 1024 * 1024))
    .build();

这里的 2MiB 是示例,需要按实际响应及并发预算选择。后续对应请求要使用 largeResponseClient。mutate() 建立修改后的副本,原 client 不会因此改变;它能保留已有配置,再叠加这项 codec 设置。

若直接从空白 WebClient.builder() 重建,需要重新核对认证 filter、基础地址、代理、连接器和超时等设置。不要为了调整容量意外丢掉原请求行为。自定义 codec 是否遵守 defaultCodecs() 的限制,也需检查其具体实现。

聚合阈值不是整个进程的内存预算。解压后的数据、解码后的对象和同时进行的多个响应都可能继续占用内存。关闭限制或给所有 client 设置极大值,会把一个可见的超限错误换成更难控制的内存压力。

大文件不要先收成一个字符串

对于大小不受控的文件或持续响应,应选择真正按块消费的路径,并明确目标文件、数据缓冲的释放、取消和异常清理。只把 bodyToMono(String.class) 改成 bodyToFlux(String.class),不能保证任意媒体类型都按预期分块,具体 codec 仍可能聚合某些内容。

落盘需要处理半文件,错误或取消时不能把未完成文件当成成功结果。涉及 DataBuffer 的自定义处理,也要核对所用操作符是否负责释放;重复释放与漏释放都可能出错。不要在事件循环上直接进行长时间阻塞的文件操作。

重试不会改变同一份响应的大小。没有幂等和次数限制的重试,可能让超限请求反复占用带宽与内存。

修改后,在隔离环境覆盖小于上限、超过上限、并发读取和读取中断。确认成功结果是完整正文,失败仍能明确报告,并观察内存使用;只有 HTTP 200 不足以作为验收。保留原 client 配置,回退时恢复对应容量与使用位置,避免留下两套 client 名称指向错误的组合。