通过Java查找服务器的互联网带宽流式传输

问题描述:

关注此主题。 Streaming large files in a java servlet通过Java查找服务器的互联网带宽流式传输

是否有可能通过java找到当前机器可用的总互联网带宽?

我想要做的是通过servlet传输大文件,基于并行请求的数量和总带宽,我试图减少每个请求的流的BUFFER_SIZE。合理?

有没有纯java的方法? (没有JNI)

也许你可以花时间多久应用程序需要发送一个包(缓冲区)。如果这大于x毫秒,则使缓冲区更小。您可以使用原始bufferSizeif (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(); 

找到可用带宽的唯一方法是监视/测量它。在Windows上,您可以访问Net.exe并获得每个NIC上的吞吐量。

+0

基于纯Java的方式 – Madhu 2009-09-29 05:14:48

+2

**这**是一个正确的答案,请回答。没有纯粹的Java方法! – 2010-07-01 11:48:40

如果您通过servlet提供内容,那么您可以计算每个servlet输出流的运行速度。为用户/会话收集所有数据流的数据,并且至少可以确定当前的带宽使用情况。

计算速率的一种可能方式可能不是通过servlet output stream写入大文件,而是写入新的FilterOutputStream,以便记录下载速率。

“当前机器上可用的全部互联网带宽”的概念很难定义。但是,调整本地缓冲区大小不会影响您可以推送到单个客户端的数据量。

给定客户端可以从服务器获取数据的速率会随客户端和时间而变化。对于任何给定的连接,您可能受到本地上行连接到Internet的限制(例如,DSL上的服务器),或者您可能受限于核心(不太可能)或远程端(例如数据中心中的服务器,客户端在拨号线上)。当你有很多连接时,每个连接可能会有不同的瓶颈。衡量这个可用带宽是一个难题;请参阅关于此主题的此列表research and tools。一般来说,TCP将公平地使用所有可用的带宽来处理任何给定的连接(尽管有时它可能会对可用带宽的变化作出反应,而不是你喜欢的)。如果客户端无法处理更多数据,写入呼叫将被阻止。

如果您发现您看到低带宽并且导致数据缓冲写入网络的原因不足,则只需调整链接问题中的buffersize即可。您可能会调整缓冲区大小的另一个原因是,如果您有太多的活动连接,并且内存不足。

在任何情况下,真正的答案可能不是缓冲,而是将您的静态文件放在单独的服务器上,并使用类似thttpd的东西来为它们服务(使用系统调用如sendfile)而不是servlet。这有助于确保瓶颈不在您的服务器上,而是在互联网中的某个地方,不受您的控制。

编辑:重新阅读这个,它有点混乱,因为它在这里迟到了。基本上,你不应该从头开始做这件事;使用现有的高度可扩展的Java服务器之一,因为他们会做得更好,更容易。

你不会喜欢这一点,但它实际上没有意义,这里的原因:

  • 总带宽是独立的连接数(虽然有一些小的开销),所以与缓冲区大小混合将无济于事
  • 无论如何,你的数据块被分解为可变大小的数据包。您的网卡和协议将比您的servlet更好地处理此问题
  • 定期调整缓冲区的大小非常昂贵 - 远远好于从固定大小的池中重新使用常量缓冲区,并且所有连接都为I/O权限排队等待
  • 有一个十亿半库,用这种服务器

的帮助这个是我,我就开始看/使用NIOØ复我。你几乎可以肯定找到一个图书馆来为你做这件事。 IBM的文章here可能是一个有用的起点。

我认为聪明的钱给你一个网络I/O线程和一个磁盘I/O线程,多路复用。每个连接都会从池中请求缓冲区,并使用数据(来自共享网络或磁盘流或通道)填充数据,对其进行处理,然后将缓冲区返回到池以供重用。不需要调整缓冲区大小,只需要等待每个数据块。如果您希望延迟保持不变,那么请限制一次可以激活多少次传输,并排队其他传输。