最初のコメントに続いて質問が編集されました。
私の問題は主に Java ソケットのパフォーマンス、特にターゲット サーバーからの読み取りに関するものです。
サーバーは単純な serversocket.accept() ループであり、Firefox からの接続ごとにクライアント スレッドを作成します。
主な問題は、膨大な時間ブロックするソケット入力ストリームの読み取りです。
クライアント スレッドは次のとおりです。
//Take an httpRequest (hc.apache.org), raw string http request, and the firefox socket outputstream
private void handle(httpRequest req, String raw, Outputstream out)
{
InputStream targetIn =null;
OutputStream targetOut = null;
Socket target = null;
try {
System.out.println("HANDLE HTTP");
String host = req.getHeaders("Host")[0].getValue();
URI uri = new URI(req.getRequestLine().getUri());
int port = uri.getPort() != -1 ? uri.getPort() : 80;
target = new Socket(host, port);
//**I have tried to play around with these but cannot seem to get a difference in performance**
target.setTcpNoDelay(true);
// target.setReceiveBufferSize(1024 *1024);
// target.setSendBufferSize(1024 * 1024);
//Get your plain old in/out streams
targetIn = target.getInputStream();
targetOut = target.getOutputStream();
//Send the request to the target
System.out.println("---------------Start response---------------");
targetOut.write(raw.getBytes());
System.out.println("request sent to target");
////Same as membrane
byte[] buffer = new byte[8 * 1024];
int length = 0;
try {
while((length = targetIn.read(buffer)) > 0) {
out.write(buffer, 0, length);
out.flush();
}
} catch(Exception e) {
e.printStackTrace();
}
System.out.println("closing out + target socket");
//IOUTILS
// long count = IOUtils.copyLarge(targetIn, out, 0L, 1048576L);
// int count = IOUtils.copy(targetIn, out);
// System.out.println("transfered : " + count );
//CHANNEL COPY
//
// ReadableByteChannel input = Channels.newChannel(targetIn);
// WritableByteChannel output = Channels.newChannel(out);
//
// ChannelTools.fastChannelCopy(input, output);
//
// input.close();
// output.close();
//CHAR TO CHAR COPY
// int c;
// while ((c = targetIn.read()) != -1) {
// out.write(c);
// }
target.close();
out.close();
System.out.println("-------------------- end response ------------------------------");
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
主な問題は、ターゲット入力ストリームをクライアント (firefox) 出力ストリームにコピーする適切な方法にあります。
これをテストするために私が使用しているサイトはhttp://www.ouest-france.fr (大量の画像があり、大量のリクエストを行う新しいサイト) です。
ワークステーションからターゲットへの Ping 時間: 10ms
iceweasel での通常の読み込み (debian firefox、firebug 時間): 14 秒、2.5MB
このプロキシの背後で読み込み中: 14 分 (firebug ネット パネルは偽の 404 でいっぱいで、一定時間後に黒に戻る要求を中止し、要求の負荷はブロックまたは待機モードになっています)
ビジュアル VM のロードアップを実行すると、(アプリが実際に時間を費やしている場所を確認するために) クラス フィルターなしでプロファイリングを開始し、その時間の 99% を java.net.SocketInputStream.read(byte[], int, int )、これはターゲット ソケット入力ストリームを読み取っています。
私は宿題を終えて、さまざまなソリューションをテストできる場所を探していたと思います。
しかし、パフォーマンスは決して向上しないようです。
私はすでに試したこと:
-入力ストリームと出力ストリームをバッファリングされたバージョンに入れますが、まったく変更はありません
-int から int へのコピー、まったく変更なし、
-classic byte[] 可変サイズの配列を使用した配列コピー、まったく変更なし
settcpnodelay、setsendbuffersize、setreceivebuffersize をいじっても、何の変化も得られませんでした。
nio socketchannels を試してみることを考えていましたが、ソケットを sslsocket ハイジャックする方法が見つかりません。
そのため、現時点では少し行き詰まっており、解決策を探しています。
私はオープンソースのプロキシのソースコードを見て、ロジックの根本的な違いを見つけることができないので、これで完全に失われています.
他のテストを試しました:
export http_proxy="localhost:4242" wget debiandvd.iso
スループットは 2MB/s に達します。また、スレッドはターゲットからの読み取りに 66% の時間を費やし、クライアントへの書き込みに 33% の時間を費やしているようです
おそらく多くのスレッドを実行する必要があると考えていますが、www.google.com でテストを実行すると、通過するリクエストははるかに少なくなりますが、それでも www.ouest-france.fr と同じ問題が発生します
Debian iso テストでは、多くのスレッドを実行する必要があると考えていました (ouest-france は約 270 リクエスト) が、Google テスト (10 リクエスト) テストでは、スレッド番号が問題ではないことを確認しているようです。
どんな助けでも大歓迎です。
環境は debian、sun Java 1.6、dev と eclipse および visualvm です。
必要に応じて残りのコードを提供できます。
ありがとうございました