我有一个基于Spring的web应用程序,它有时需要以多部分文件的形式发送和接收可能很大的文档。上传文件时,它们通常会直接写入数据库。当下载时,总是在没有任何处理的情况下读取和发送。在进行负载测试时,应用程序开始抛出OutOfMemoryErrors。为了解决这个问题,而不是将一个完整的多部分文件加载到内存中,我直接在请求/响应输入/输出流和db中的blob之间进行读写。正如预期的那样,这修复了OutOfMemoryErrors。然而,在低负载情况下,应用程序的执行速度会慢3-7倍。
我认为,为了将整个多部分文件加载到内存中并注入到控制器中,它仍然需要通过相同请求的输入流和底层套接字进行读取。Spring如何加载由同一客户端发送的相同文件,速度比直接读取它们快得多?
编辑:重点是低负载。一旦它运行了足够长的时间或足够高的负载,性能将进一步恶化,因为(我猜) gc必须持续运行。那之前呢?
添加相关代码:基本上是这种类型的控制器
public ResponseEntity<String> saveStuff(..., MultipartFile file){
....
dao.save(..., file.getBytes());
}被替换为
public ResponseEntity<String> saveStuff(..., HttpServletRequest request){
....
dao.save(..., request.getInputStream());
}在dao中,将输入流写入blob的部分是
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();
}
}发布于 2016-01-27 12:16:32
您的代码甚至都不正确,所以您为什么要担心它的性能并不清楚。试试这个:
int count;
byte[] buffer = new byte[8192];
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}与您的不同,这个版本正确地写入了最终的部分缓冲区。
至于性能,我会尝试更大的缓冲区大小,32k或更多。
发布于 2016-01-28 04:54:23
所以基本上整个问题都是在过度思考一个简单的问题。它实际上不是关于读取请求的输入,而是将其写入数据库,这是很慢的。基本上,所有需要发生的事情不再是摆弄缓冲区和读写字节,而是
statement.setBinaryStream(paramIndex, requestInputStream, contentLength);
//....execute statement and stuff....https://stackoverflow.com/questions/35028011
复制相似问题