|
|
1
57
如果可能,您不应该将要提供服务的文件的全部内容存储在内存中。相反,获取数据的InputStream,并将数据分块复制到Servlet OutputStream。例如:
我同意托比的观点,你应该“把他们指向S3URL” 至于OOM异常,您确定它与提供图像数据有关吗?假设JVM有256MB的“额外”内存用于提供图像数据。在谷歌的帮助下,“256MB/200KB”=1310。对于2GB的“额外”内存(现在是一个非常合理的数量),可以支持超过10000个并发客户端。即便如此,1300个并发客户端仍然是一个相当大的数字。这是您所经历的负载类型吗?如果不是,您可能需要在其他地方查找OOM异常的原因。 编辑-关于:
几周前,当我阅读S3文档时,我注意到您可以生成可以附加到S3URL的过期密钥。因此,您不必向公众开放S3上的文件。我对该技术的理解是:
|
|
|
2
17
你为什么不直接把它们指向S3URL呢?从S3获取一个工件,然后通过您自己的服务器将其流式传输给我,这与使用S3的目的背道而驰,S3的目的是为了将为Amazon提供图像服务的带宽和处理过程卸载。 |
|
|
3
11
我见过很多代码,比如john vasilef(目前已被接受)的答案,一个紧密的while循环,从一个流中读取块并将它们写入另一个流。 我的论点是反对不必要的代码复制,支持使用Apache的IOUtils。如果您已经在其他地方使用它,或者您正在使用的另一个库或框架已经依赖于它,那么这是一条已知且经过良好测试的单行线。 在下面的代码中,我将在servlet中将一个对象从AmazonS3流式传输到客户机。
6行定义明确的模式和适当的流关闭似乎相当坚实。 |
|
|
4
2
托比是对的,如果可以的话,你应该直接指向S3。如果你不能回答,那么这个问题就有点模糊,无法给出准确的回答:
您的java堆有多大?内存不足时,有多少流同时打开?
如果您使用8K缓冲区,那么在~8meg的堆空间中可能会有1000个并发流,因此您肯定做错了。。。。
|
|
|
5
2
我非常同意toby和John Vasileff的观点——如果您能够容忍相关问题,S3非常适合卸载大型媒体对象。(我们自己的应用程序的一个实例对10-1000MB FLV和MP4执行此操作。)例如:没有部分请求(字节范围标头)。必须“手动”处理,偶尔停机等。。 如果这不是一个选项,John的代码看起来不错。我发现2k FILEBUFFERSIZE的字节缓冲区在microbench标记中是最有效的。另一个选项可能是共享文件通道。(文件通道是线程安全的。) 也就是说,我还要补充一点,猜测导致内存不足错误的原因是一个典型的优化错误。你可以通过努力工作来提高成功的机会。
当然还有其他工具,但是jmap&jhat附带Java 5+“开箱即用”
啊,我不认为你做不到。即使你可以,这听起来也很可疑。管理连接的tomcat线程需要控制。如果遇到线程不足,请增加./conf/server.xml中的可用线程数。同样,度量是检测这一点的方法——不要只是猜测。 问题:您是否也在EC2上运行?tomcat的JVM启动参数是什么? |
|
|
6
0
您必须检查两件事:
|
|
|
7
0
除了John建议的之外,还应该反复刷新输出流。根据web容器的不同,它可能缓存部分甚至所有输出,并立即刷新(例如,计算内容长度标题)。那会烧掉很多记忆。 |
|
|
8
0
如果您可以对文件进行结构化,使静态文件彼此独立并位于各自的存储桶中,那么使用Amazon S3 CDN可能会获得当今最快的性能, CloudFront . |