通过Java查找服务器的互联网带宽流式传输
关注此主题。 Streaming large files in a java servlet。通过Java查找服务器的互联网带宽流式传输
是否有可能通过java找到当前机器可用的总互联网带宽?
我想要做的是通过servlet传输大文件,基于并行请求的数量和总带宽,我试图减少每个请求的流的BUFFER_SIZE。合理?
有没有纯java的方法? (没有JNI)
也许你可以花时间多久应用程序需要发送一个包(缓冲区)。如果这大于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();
找到可用带宽的唯一方法是监视/测量它。在Windows上,您可以访问Net.exe并获得每个NIC上的吞吐量。
如果您通过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线程,多路复用。每个连接都会从池中请求缓冲区,并使用数据(来自共享网络或磁盘流或通道)填充数据,对其进行处理,然后将缓冲区返回到池以供重用。不需要调整缓冲区大小,只需要等待每个数据块。如果您希望延迟保持不变,那么请限制一次可以激活多少次传输,并排队其他传输。
基于纯Java的方式 – Madhu 2009-09-29 05:14:48
**这**是一个正确的答案,请回答。没有纯粹的Java方法! – 2010-07-01 11:48:40