我正在构建需要扩展的Java服务器。Servlet之一将提供存储在Amazon S3中的图像。
最近,在负载下,我的VM内存不足,这是在我添加了为图像提供服务的代码之后,因此,我很确定流较大的servlet响应会引起我的麻烦。
我的问题是:从数据库或其他云存储中读取时,如何编写Java Servlet来将大型(> 200k)响应流回浏览器,是否有最佳实践?
我考虑过将文件写入本地临时驱动器,然后生成另一个线程来处理流,以便可以重新使用tomcat servlet线程。这似乎很沉重。
任何想法将不胜感激。谢谢。
如果可能,你不应将要提供的文件的全部内容存储在内存中。取而代之的是,为数据获取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上的文件。我对这项技术的理解是: