首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >文件上载到servlet优化

文件上载到servlet优化
EN

Stack Overflow用户
提问于 2016-01-27 10:56:28
回答 2查看 384关注 0票数 0

我有一个基于Spring的web应用程序,它有时需要以多部分文件的形式发送和接收可能很大的文档。上传文件时,它们通常会直接写入数据库。当下载时,总是在没有任何处理的情况下读取和发送。在进行负载测试时,应用程序开始抛出OutOfMemoryErrors。为了解决这个问题,而不是将一个完整的多部分文件加载到内存中,我直接在请求/响应输入/输出流和db中的blob之间进行读写。正如预期的那样,这修复了OutOfMemoryErrors。然而,在低负载情况下,应用程序的执行速度会慢3-7倍。

我认为,为了将整个多部分文件加载到内存中并注入到控制器中,它仍然需要通过相同请求的输入流和底层套接字进行读取。Spring如何加载由同一客户端发送的相同文件,速度比直接读取它们快得多?

编辑:重点是低负载。一旦它运行了足够长的时间或足够高的负载,性能将进一步恶化,因为(我猜) gc必须持续运行。那之前呢?

添加相关代码:基本上是这种类型的控制器

代码语言:javascript
复制
 public ResponseEntity<String> saveStuff(..., MultipartFile file){
    .... 
    dao.save(..., file.getBytes());
 }

被替换为

代码语言:javascript
复制
 public ResponseEntity<String> saveStuff(..., HttpServletRequest request){
    .... 
    dao.save(..., request.getInputStream());
 }

在dao中,将输入流写入blob的部分是

代码语言:javascript
复制
try {
    byte[] bytesRead = new byte[4096];
    while (in.read(bytesRead, 0, bytesRead.length) != -1) {
        toBlob.write(bytesRead);
    }
} catch (IOException e) {
   e.printStackTrace();
} finally {
    try {
        in.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        toBlob.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
EN

回答 2

Stack Overflow用户

发布于 2016-01-27 12:16:32

您的代码甚至都不正确,所以您为什么要担心它的性能并不清楚。试试这个:

代码语言:javascript
复制
int count;
byte[] buffer = new byte[8192];
while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

与您的不同,这个版本正确地写入了最终的部分缓冲区。

至于性能,我会尝试更大的缓冲区大小,32k或更多。

票数 1
EN

Stack Overflow用户

发布于 2016-01-28 04:54:23

所以基本上整个问题都是在过度思考一个简单的问题。它实际上不是关于读取请求的输入,而是将其写入数据库,这是很慢的。基本上,所有需要发生的事情不再是摆弄缓冲区和读写字节,而是

代码语言:javascript
复制
statement.setBinaryStream(paramIndex, requestInputStream, contentLength);
//....execute statement and stuff....
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35028011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档