关注此主题。 Streaming large files in a java servlet
是否可以通过java找到当前机器中可用的总互联网带宽?
我想要做的是在通过servlet传输大文件时,根据并行请求的数量和总带宽我试图减少每个请求的流的BUFFER_SIZE。合理?
有没有纯粹的java方式? (没有JNI)
答案 0 :(得分:6)
也许您可以计算应用程序需要多长时间发送一个包(缓冲区)。如果大于x毫秒,则使缓冲区变小。您可以为原始bufferSize
和if (stop - start > 700)
使用其他值。
这是基于您注意到的主题:
ServletOutputStream out = response.getOutputStream();
InputStream in = [ code to get source input stream ];
String mimeType = [ code to get mimetype of data to be served ];
int bufferSize = 1024 * 4;
byte[] bytes = new byte[bufferSize];
int bytesRead;
response.setContentType(mimeType);
while ((bytesRead = in.read(bytes)) != -1) {
long start = System.currentTimeMillis();
out.write(bytes, 0, bytesRead);
long stop = System.currentTimeMillis();
if (stop - start > 700)
{
bufferSize /= 2;
bytes = new byte[bufferSize];
}
}
// do the following in a finally block:
in.close();
out.close();
答案 1 :(得分:0)
找到可用带宽的唯一方法是监控/测量它。在Windows上,您可以访问Net.exe,并可以获得每个NIC上的吞吐量。
答案 2 :(得分:0)
如果您通过servlet提供内容,则可以计算每个servlet输出流的速度。收集用户/会话的所有流的数据,您至少可以确定当前带宽使用情况。
计算费率的一种可能方法可能是通过servlet output stream写入大文件,而不是写入可以跟踪下载速率的新FilterOutputStream。
答案 3 :(得分:0)
“当前机器中可用的总互联网带宽”的概念很难定义。但是,调整本地缓冲区大小不会影响您可以将数据推送到单个客户端的数量。
给定客户端从服务器获取数据的速率因客户端和时间而异。对于任何给定的连接,您可能受到本地上游连接到Internet的限制(例如,DSL上的服务器),或者您可能受限于核心(不太可能)或远程端(例如,数据中心中的服务器,客户端)在拨号线上)。当您有许多连接时,每个单独的连接可能会有不同的瓶颈。测量这个可用带宽是一个难题;例如,请参阅此主题的research and tools列表。
通常,TCP将处理使用所有可用带宽的任何给定连接(尽管有时它可能会对可用带宽的变化做出反应,而不是你喜欢的)。如果客户端无法处理更多数据,则写入调用将阻止。
如果您发现您看到的带宽较低,并且其原因是缓冲的数据不足以写入网络,则您只需要调整链接问题中的buffersize。您可能调整缓冲区大小的另一个原因是,如果您有这么多活动连接,那么内存不足。
在任何情况下,真正的答案可能是根本不缓冲,而是将静态文件放在单独的服务器上并使用thttpd之类的东西来提供服务(使用类似sendfile的系统调用而不是servlet。这有助于确保瓶颈不在您的服务器上,而是在互联网的某个地方,超出您的控制范围。
答案 4 :(得分:0)
编辑:重读这个,有点糊涂,因为它已经很晚了。基本上,你不应该从头开始这样做;使用现有的高度可扩展的Java服务器之一,因为它们会更好,更容易。
你不会喜欢这个,但它实际上没有意义,,这就是原因:
如果是这样的话,我会开始使用NIO查看多路复用I / O.你几乎可以肯定找到一个库来为你做这件事。 IBM文章here可能是一个有用的起点。
我认为智能资金为您提供了一个网络I / O线程和一个磁盘I / O线程,并提供了多路复用。每个连接从池请求缓冲区,用数据(来自共享网络或磁盘流或通道)填充它,处理它,然后将缓冲区返回池以供重用。没有重新调整缓冲区大小,只需要等待每个数据块。如果您希望延迟保持简短,那么一次限制可以激活的传输数量,并排队其他传输。