当并行发生过多上传(堆空间)时,JVM / Tomcat会崩溃?

时间:2013-08-26 00:03:53

标签: java spring servlets grails jvm

我在Tomcat 7上运行了一个Servlet应用程序。我在setenv.sh中设置了以下内容

CATALINA_OPTS="
-server 
-Xms1G 
-Xmx5G
-XX:MaxPermSize=512m
-Dfile.encoding=UTF-8";

服务器在Ubuntu 12.04LTS上运行,有6个内核和8GB内存。 我的应用程序是Grails / Spring / Java应用程序,用户可以上传图像。有时会发生3-5个用户同时开始上传图像。在这些情况下,我的Tomcat因以下错误而崩溃:

java.lang.OutOfMemoryError: Java heap space

我知道我必须增加Tomcat的Xmx参数以防止出现此问题。但严重的是我的情况有什么问题?

  1. 在我的方案中是否有处理文件上传的最佳做法?

  2. 我可以预防这个问题吗?我的意思是当5GB不足以进行3-5次并行上传时,我需要多少资源来进行数百次并行上传?

  3. 我的应用程序如此糟糕或文件上传需要如此多的资源是否正常?

  4. 注意:用户上传的文件为2-8 MB。

    这就是我在视图中进行上传的方式:

       <g:form method="post" action="save" enctype="multipart/form-data">
        <input type="file" name="file"/>
        <input type="submit"/>
       </g:form>
    

    并在我的控制器中:

    def file = request.getFile('image')
    byte [] byteFile = file.getBytes()
    

    在config / spring / resource.groovy中我做了:

    beans = { 
      multipartResolver(org.springframework.web.multipart.commons.CommonsMultipartResolver){
    
            // Max in memory 100kbytes
            maxInMemorySize=102400
    
        }
    
    } 
    

    上传的文件是图片。它们将被缩放并保存到磁盘。

    图像将保存为:

    bytes [] currentImage = // some image in bytes ...
    def newFile = new FileOutputStream(fullPath)
    newFile.write(currentImage)
    newFile.close()
    

1 个答案:

答案 0 :(得分:1)

避免使用MultipartFile.getBytes(),而是使用MultipartFile.getInputStream()来避免将整个文件内容读入内存。

所以将代码更改为:

def file = request.getFile('image')
InputStream inputStream = file.inputStream

您尚未提及对上传文件执行的操作,但请确保在应用程序的各个层中传递InputStream,如果要最小化堆,请不要转换为byte[]的使用。