我们HttpServer
在项目中使用内部类通过 HTTP 在客户端和服务器之间交换数据。当我们切换到 Java 7 时,我们意识到交付结果的延迟。我们可以将问题简化为以下示例:
类EchoServer
创建上下文,该上下文/echo
仅在每个请求时返回当前日期和请求 URI。然后,该服务由客户端循环调用。
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 上执行,则一切正常,并且大约会打印一个结果。每 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
似乎在某处隐藏了 1000 毫秒的超时。InputStreamReader
如果字符是在 上而不是在上读取的,则会BufferedReader
发生相同的延迟。如果直接从输入流中读取一个字节,则看不到延迟。另一方面,如果EchoClient
程序是针对 servlet 运行的,那么一切正常,与是否使用 theBufferedReader
或 the无关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 毫秒)。