プロジェクトで内部HttpServer
クラスを使用して、HTTP を介してクライアントとサーバー間でデータを交換しています。Java 7 に切り替えたときに、結果の配信が遅れていることに気付きました。問題を次のサンプルに減らすことができます。
クラスは、リクエストごとに現在の日付とリクエスト URI を単純に返すEchoServer
コンテキストを作成します。/echo
このサービスは、ループ内のクライアントによって呼び出されます。
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.Date;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class EchoServer {
public static void main(String[] args) throws IOException {
HttpServer server = HttpServer.create(new InetSocketAddress(80), 0);
server.createContext("/echo", new EchoHandler());
server.start();
}
static class EchoHandler implements HttpHandler {
public void handle(HttpExchange httpExchange) throws IOException {
httpExchange.getResponseHeaders().add("Content-type", "text/html");
String response = "<b>" + new Date() + "</b> for " + httpExchange.getRequestURI();
httpExchange.sendResponseHeaders(200, response.length());
OutputStream os = httpExchange.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
次のクライアントは、クラスを使用して無限ループでサービスを呼び出し、URL
返されたストリームから最初の文字 (<
記号) を出力します。さらに、クライアントは現在の時刻を出力します。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
public class EchoClient {
public static void main(String[] args) throws Exception{
while(true) {
URL url = new URL("http://localhost:80/echo");
BufferedReader rd = new BufferedReader(new InputStreamReader(url.openStream()));
int res = rd.read();
System.out.println((char)res);
System.out.println(System.currentTimeMillis());
}
}
}
このコードを Java6 で実行すると、すべてが正常に機能し、結果が約 1 秒で出力されます。5ミリ秒ごと。
% java -version
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode)
% java EchoClient
<
1362515635677
<
1362515635682
<
1362515635687
<
1362515635691
コードが Java7 で実行される場合、各リクエストは約 1000 ミリ秒を使用します。
% java -version
java version "1.7.0_17"
Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)
% java EchoClient
<
1362517297845
<
1362517298844
<
1362517299845
<
1362517300845
1000msのタイムアウトがどこかに隠されているようです。InputStreamReader
文字がではなくで読み取られる場合BufferedReader
、同じ遅延が発生します。バイトが入力ストリームから直接読み取られる場合、遅延は見られません。一方、プログラムがサーブレットに対して実行される場合、または が使用されているEchoClient
かどうかに関係なく、すべてが正常に機能します。BufferedReader
InputStreamReader
そのクラスInputStreamReader
は、HttpServer の Java 7 実装によって提供されなくなったサーバーから何かを期待しているようです。ここで正確に何が起こっているのか、この問題をどのように解決できるのか考えていますか? 回避策はありますか?それともこれはバグですか?
ありがとう!
クライアント コードにさらにタイミングを追加しました。
public static void main(String[] args) throws Exception{
while(true) {
System.out.println("0: "+System.currentTimeMillis());
URL url = new URL("http://localhost:80/echo");
System.out.println("1: "+System.currentTimeMillis());
InputStream in = url.openStream();
System.out.println("2: "+System.currentTimeMillis());
InputStreamReader isr = new InputStreamReader(in);
System.out.println("3: "+System.currentTimeMillis());
char res = (char)isr.read(); // character read is `<`
System.out.println(res + ": "+System.currentTimeMillis());
}
}
次の結果が得られます。
% java EchoClient
0: 1362532555535
1: 1362532555537
2: 1362532555608
3: 1362532555609
<: 1362532555611
0: 1362532555612
1: 1362532555613
2: 1362532556608
3: 1362532556609
<: 1362532556610
0: 1362532556611
1: 1362532556612
2: 1362532557609
3: 1362532557610
<: 1362532557611
0: 1362532557612
1: 1362532557613
の最初の呼び出しにopenStream
はある程度の時間がかかります (70 ミリ秒) が、それ以降のすべての呼び出しにはさらに時間がかかりますopenStream
(約 996 ミリ秒)。