当前位置: 首页 > 知识库问答 >
问题:

上传大文件导致堆空间Java

公羊嘉
2023-03-14

可能没有多少开发人员像我一样面临这个问题<但是我想分享我已经解决了将近一个月的解决方案
我使用Kubernetes和docker compose,此Webflux服务(容器)设置了内存限制1gmem\u limit:1g我不允许增加内存限制

已将coRouter用作容器中的控制器。

@Configuration
class WebController(
) {

    @Bean
    fun endpoints() = coRouter {
        contentType(MediaType.MULTIPART_FORM_DATA).nest {
            POST("/uploadFile") { requestParm ->
                requestParm.awaitMultipartData().multipartFormData["file"]?.first()
            }
        }
    }
}

如果我使用APIhttp://localhost:9004/uploadFile100MB上传文件,10个文件(使用JS Ajax)
它会产生java.lang.OutOfMemoryError:Java堆空间,因为它没有足够的内存。
每当您调用Request estParm.awaitMultipartData()时,它会将这些字节流式传输到内存中。


共有1个答案

南宫星波
2023-03-14

我意识到,我当前的代码将把上传的文件直接存储在内存中。有两种方法可以解决此问题。

  • 第一种方式,在路由器或控制器上添加EnableWebFlux

@Configuration
@EnableWebFlux
class WebController(
) { }
  • 第二种方式,从DelegatingWebFluxConfiguration扩展到路由器或控制器参考:https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-配置高级java
@Configuration
class WebController(
): DelegatingWebFluxConfiguration() { }

为什么解决了上传大文件的问题?

以上这两种方式将自动用于Super类的方法configureHttpMessageCodecs(configurer:ServerCodeConfigurerhttps://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-编解码器多部分

默认情况下,使用DefaultPartHttpMessageReader,但这可以通过ServerCodeConfigurer进行更改。有关DefaultPartHttpMessageReader的更多信息,请参阅DefaultPartHttpMessageReader的javadoc。

如您所见,ServerCodeConfigurer默认情况下将使用DefaultPartHttpMessageReader。

DefaultPartHttpMessageReader有这个重要的属性MaxInMemorySize(如果内存已满,存储在磁盘中)

https://docs.spring.io/spring-framework/docs/5.3.1/javadoc-api/org/springframework/http/codec/multipart/DefaultPartHttpMessageReader.html#setMaxInMemorySize-int-

配置每个部分允许的最大内存量。当超过限制时:文件部分被写入临时文件。非文件部分被拒绝使用DataBufferLimitException。默认情况下,这设置为256K。

上传文件的默认内存是256K
如果内存已满,它会将这些文件暂时保存到磁盘。

您还可以自定义内存来存储大小文件Spring WebFlux:设置上载文件的最大文件大小

 类似资料:
  • 问题内容: 我正在使用ImageIO API编写PNG文件。在循环中调用此代码,并导致OutOfMemory错误。无论如何,可以固定以下代码来避免OutOfMemory错误吗?还是增加JVM堆大小的唯一选择? Java堆大小为1024M。 问题答案: 我遇到了类似的问题,我必须读取36张图像,将它们裁剪并保存到一个新文件中(一次一个)。我发现必须在每次迭代后将图像设置为null,以允许Java进行

  • 我试图将整个文件作为字符串对象加载到内存中。但是在应用程序结束后,我的内存不会被释放回垃圾收集器。我知道在内存中读取整个文件是不好的,但是我必须将数据发送到另一个类,有人能帮助我如何做这只是一个流,而不是将整个代码加载到内存中,如果没有,有人能说我现在的代码有什么问题吗

  • 我正在尝试编写一个RESTAPI,允许用户下载大文件(即 ContentCachingResponseWrapper中的默认flushBuffer()方法为空。如果我尝试调用copyBodyToResponse(),它用于将数据从缓存复制到流,它工作正常,但也会关闭流。这导致只向客户端发送第一块数据。 有什么建议吗? 我发现以下错误:

  • 我们正在开发需要使用Azure作为文件内容存储的文档微服务。Azure Block Blob似乎是一个合理的选择。文档服务的堆限制为512MB()。 我没有成功地让流文件上传与有限的堆使用(也在上测试)。 尝试了以下方法: 使用 结果:-SDK尝试使用标记/重置,即使文件输入流报告不支持此功能。 结果:。我假设SDK试图将所有1.17GB的文件内容加载到内存中。 结果:使用了1.5GB堆内存,所有

  • 我上传文件有问题。我正在使用codeigniter框架和dropzone。js上传文件。 我认为: 控制器: 问题是上传的文件返回为空: 数组(1){["upload_data"]= 我试图转储fileToUpload输入的POST值,也是空的。是不是我忽略了什么?

  • 问题内容: 我在执行多线程程序时遇到以下错误 上面的错误发生在其中一个线程中。 据我所知,堆空间仅由实例变量占用。如果这是正确的,那么为什么在运行一段时间后会出现此错误,因为在创建对象时分配了实例变量的空间。 有什么办法可以增加堆空间? 我应该对程序进行哪些更改,以使其占用更少的堆空间? 问题答案: 如果要增加堆空间,可以 -在命令行上使用。默认情况下,这些值基于JRE版本和系统配置。你可以在Ja