2013-08-26 49 views
0

我在Tomcat 7运行的Servlet应用我设置setenv.sh以下当并行发生太多上传时(堆空间)JVM/Tomcat崩溃?

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. 我的应用程序如此糟糕,还是正常的文件上传需要这么多资源?

注意:用户上传的文件为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() 

在配置/春/ 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() 
+0

这些文件有多大?尝试使用jvisualvm来查看抓取所有内存的内容。 – BevynQ

+1

您的应用程序在上传过程中是否将整个文件内容保存在内存中?这是可能的流文件上传,commons-fileupload支持:http://commons.apache.org/proper/commons-fileupload/streaming.html – samlewis

+0

@samlewis如何使用Grails完成文件上传流?你能制定一个答案吗? – confile

回答

1

避免MultipartFile.getBytes(),使用MultipartFile.getInputStream()来避免读取整个文件内容到内存中。

所以你的代码更改为:

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

你没有提到你上传的文件怎么做,但请确保在整个应用程序的层层传递InputStream,不转换成byte[]如果你想尽量减少堆的使用。

+0

你可以发表我应该如何改变我的代码,以获得与您的建议文件的字节? – confile

+0

上传的文件是图像。它们将被缩放并保存到磁盘。我更新了我的答案。如何将图像作为inputStream呈现给磁盘?为什么字节[]不好? – confile

+0

缩放可能需要将图像读入内存,因此流式传输可能不适合您。我会回到@BevynQ的建议与JVisualVM分析。 byte []是不好的,因为它是内存中的整个文件内容,但对你而言,这可能是不可避免的。 – samlewis

相关问题