当前位置: 首页 > 工具软件 > limiton > 使用案例 >

Gateway 报错org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes..

汲雅珺
2023-12-01

Spring Boot 版本:2.6.6

Spring Cloud Gateway 版本:3.1.1

由于在 Gateway 的自定义过滤器中重写了请求 ServerRequest,后面因为升级了架构,原本旧版本未对请求参数的大小进行限制(默认取-1),后面升级了新版修改为 256KB 的限制。

解决方案如下:

方案一跟二对于我当然版本的 SpringBoot 不生效,大家可以都尝试一下,有可能可以。

一、设置配置文件(失败)

spring:
  codec:
    max-in-memory-size: 50MB

二、添加配置 Bean(失败)

@Configuration
@EnableWebFlux
public class WebFluxWebConfig implements WebFluxConfigurer
{
	@Override
	public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
		configurer.defaultCodecs().maxInMemorySize(50 * 1024 * 1024);
	}
}

三、手动设置配置类 ServerCodecConfigurer成功
博主的场景是拿出请求的 body,由于只能取一次需要重新创建 Request,create 的第二个参数就是 Readers

// 第二个参数 redaers 是从 ServerCodecConfigurer 获取的
ServerRequest serverRequest = ServerRequest.create(exchange, readers);

该方案是在 Github Spring 仓库的 issue 看到的解决方案,结合自己的实际场景改的,是否有效还得自己尝试一下。

@Autowired
private ServerCodecConfigurer serverCodecConfigurer;

@PostConstruct
public void init() {
    ServerCodecConfigurer.ServerDefaultCodecs serverDefaultCodecs = serverCodecConfigurer.defaultCodecs();
    // 设置限制 50MB
    serverDefaultCodecs.maxInMemorySize(50 * 1024 * 1024);
}


原因分析:

通过设置默认的 maxInMemorySize会将原有的所有 Readers 实现类删除,并根据你设置的大小重新新建,因此只需要在初始化时设置即可。由于会新建对象,务必不要在过滤器的方法中设置,造成不必要的性能损耗。

/**
 * Reset and initialize typed readers.
 * @since 5.3.3
 */
protected void initTypedReaders() {
    // 删除所有 Readers
    this.typedReaders.clear();
    // 重新添加 Readers
    addCodec(this.typedReaders, new DecoderHttpMessageReader<>(new ByteArrayDecoder()));
    // 略...
}

addCodec 方法会重新设置 reader 的 maxInMemorySize 大小

/**
 * Initialize a codec and add it to the List.
 * @since 5.1.13
 */
protected <T> void addCodec(List<T> codecs, T codec) {
    initCodec(codec);
    codecs.add(codec);
}

private void initCodec(@Nullable Object codec) {
    // 略...
    Integer size = this.maxInMemorySize;
    if (size != null) {
        if (codec instanceof AbstractDataBufferDecoder) {
		    // 重新设置的大小
            ((AbstractDataBufferDecoder<?>) codec).setMaxInMemorySize(size);
        }
    }
    // 略...
}

该文章对你有帮助吗?别忘了点赞加关注•᷄ࡇ•᷅

 类似资料: