2009-08-04 8 views
2

このスレッドに続いて Streaming large files in a java servletストリーミングのためにサーバーのインターネット帯域幅からJavaを見つける

java経由で現在のマシンで利用可能なインターネット帯域幅の合計を見つけることはできますか?

私がしようとしているのは、並列リクエストの数と合計帯域幅に基づいて、サーブレットを介して大きなファイルをストリーミングするときに、各リクエストのストリームのBUFFER_SIZEを減らそうとしています。理にかなっている?

純粋なJavaの方法はありますか? (JNIなし)

答えて

6

多分、1つのパッケージ(バッファ)を送信する必要がある時間を計測できます。それが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(); 
+2

視聴者への注意:システムは自動的にこの回答を「受け入れ」として選択しましたが、正解はありません。 – Madhu

+0

ありがとうございました。 –

0

利用可能な帯域幅を見つける唯一の方法は、それを監視/測定することです。 Windowsでは、Net.exeにアクセスでき、各NICでスループットを取得できます。

+0

純粋なJavaの道 – Madhu

+2

**これは**正しい答えはあるに基づいて回答してください。純粋なJavaの方法はありません! –

0

サーブレットでコンテンツを提供している場合は、各サーブレット出力ストリームの速さを計算できます。ユーザー/セッションのすべてのストリームのデータを収集し、少なくとも現在の帯域幅の使用状況を判断できます。

レートを計算する方法は、大きなファイルをservlet output streamで書き込む代わりに、ダウンロードレートを追跡する新しいFilterOutputStreamに書き込むことができます。

0

"現在のマシンで利用可能な総インターネット帯域幅"の概念は、定義するのが本当に難しいです。ただし、ローカルバッファサイズを調整しても、個々のクライアントにどれだけのデータをプッシュスルーできます。

特定のクライアントがサーバーからデータを取得できる速度は、クライアントおよび時間によって異なります。任意の接続では、インターネットへのローカルアップストリーム接続(DSL上のサーバーなど)によって制限されている場合や、コア(おそらく)またはリモートエンドのどこかに制限されている場合があります(たとえば、ダイヤルアップ回線で)。多くの接続がある場合、個々の接続ごとに異なるボトルネックが発生する可能性があります。この利用可能な帯域幅を測定することは難しい問題です。たとえば、対象のresearch and toolsのこのリストを参照してください。

一般に、TCPは任意の接続に対して公平にすべての利用可能な帯域幅を使用して処理します(ただし、利用可能な帯域幅の変更が好きなときより遅くなることがあります)。クライアントがさらにデータを処理できない場合、書き込み呼び出しはブロックされます。

帯域幅が狭く、その原因がネットワークに書き込むためにバッファリングされたデータが不十分であることが判明した場合は、リンクされた質問のバッファサイズを微調整するだけで済みます。バッファサイズを微調整する別の理由は、メモリが不足しているアクティブな接続が非常に多い場合です。いずれの場合においても

、本当の答えは、すべてのバッファではなく、別のサーバー上の静的ファイルを置く代わりに、サーブレットの( sendfileなどのシステムコールを使用して)それらを提供するために thttpdのようなものを使用しないようにすることがあります。これにより、ボトルネックがサーバー上になく、インターネット上のどこかにあることをコントロールすることができます。

0

EDIT:これを改めて読んだところ、ここに遅れているのでちょっと混乱しています。基本的に、最初からこれを行う必要はありません。既存の高度にスケーラブルなJavaサーバーの1つを使用してください。

あなたはこれが好きでするつもりはないが、それは実際には意味をなさない、とここに理由です:いくつかの小さなオーバーヘッドがあるが総帯域幅は接続数(とは無関係です

  • )、バッファサイズを混乱させるとあまり役に立ちません。
  • あなたのチャンクは、とにかに可変サイズのパケットに分割されています。ネットワークカードとプロトコルは、サーブレットよりもこれを処理します
  • 定期的にバッファのサイズを変更するのは高価です。固定サイズのプールから定数バッファを再利用し、すべての接続をI/O権限のためにキューに入れる方がはるかに良い
  • サーバー

この種のを支援億半のライブラリがありますが、これは私だったの、私はNIOを使用してO /多重化Iを見て開始します。これを行うためのライブラリを見つけることはほぼ確実です。 IBMの記事hereは、有用な出発点になる場合があります。

私は、スマートマネーが、ネットワークI/Oスレッド1つと、ディスクI/Oスレッド1つを多重化していると思います。各接続はプールからバッファを要求し、共有ネットワークまたはディスクのストリームまたはチャネルからデータを入力して処理し、バッファをプールに戻して再利用します。バッファのサイズを変更する必要はなく、データの各チャンクを少し待つだけです。レイテンシを短くしたい場合は、一度にアクティブにできる転送の数を制限し、他のものをキューに入れてください。

関連する問題