如果可能,您不应该将要提供的文件的全部内容存储在内存中。相反,获取数据的InputStream,并将数据分段复制到Servlet OutputStream。例如:
ServletOutputStream out = response.getOutputStream();
InputStream in = [ code to get source input stream ];
String mimeType = [ code to get mimetype of data to be served ];
byte[] bytes = new byte[FILEBUFFERSIZE];
int bytesRead;
response.setContentType(mimeType);
while ((bytesRead = in.read(bytes)) != -1) {
out.write(bytes, 0, bytesRead);
}
// do the following in a finally block:
in.close();
out.close();
我同意toby,你应该改为“将它们指向S3 url”。
至于OOM异常,你确定它与提供图像数据有关吗?假设您的JVM有256MB的“额外”内存用于提供图像数据。在Google的帮助下,“256MB/200KB”= 1310.对于2GB“额外”内存(这些日子里非常合理的数量),可以支持超过10,000个并发客户端。即便如此,1300个并发客户端也是相当大的一部分。这是你经历的负荷类型吗?如果没有,您可能需要在别处寻找OOM异常的原因。
编辑 - 关于:
在这种情况下,使用图像可以包含敏感数据...
当我通过S3文档几个星期前看,我注意到,你可以生成可以连接到S3 URL的超时密钥。所以,你不必在S3上向公众开放这些文件。我对技术的理解是:
- 初始HTML页面有下载链接到你的web应用下载链接
- 你的web应用程序生成包括到期的一个关键的S3 URL上
- 用户点击,可以说, 5分钟。
- 使用步骤3中的URL发送HTTP重定向到客户端。
- 用户从S3下载文件。即使下载时间超过5分钟,这也可以工作 - 一旦下载开始,它可以继续完成。
嗯,由于没有设置内容长度,所以servlet容器必须进行缓冲,因为在流式传输任何数据之前需要设置内容长度头。所以不知道你节省了多少内存? – 2012-02-01 15:54:36
彼得,如果你不能直接指向用户的云服务URL,并且你想设置内容长度头,并且你不知道大小,并且你不能查询云服务的大小,那么我猜你的最好的办法是首先流到服务器上的临时文件。当然,在将第一个字节发送到客户端之前,在服务器上保存副本可能会导致用户认为请求失败,具体取决于云 - >服务器传输需要多长时间。 – 2012-02-13 03:55:37