(在ServerFault中查看此问题)
我有一个Java客户端,它使用Socket打开到同一台机器的并发连接.我正在目睹一种请求完成速度非常快的现象,但其他请求的延迟时间为100-3000毫秒.使用Wireshark进行数据包检查会在离开客户端之前显示所有SYN数据包超出第一个等待很长时间.我在Windows和Linux客户端都看到了这一点.可能是什么导致了这个?当客户端是Windows 2008或Linux机器时,会发生这种情况.
附加代码:
import java.util.*;
import java.net.*;
public class Tester {
public static void main(String[] args) throws Exception {
if (args.length < 3) {
usage();
return;
}
final int n = Integer.parseInt(args[0]);
final String ip = args[1];
final int port = Integer.parseInt(args[2]);
ExecutorService executor = Executors.newFixedThreadPool(n);
ArrayList<Callable<Long>> tasks = new ArrayList<Callable<Long>>();
for (int i = 0; i < n; ++i)
tasks.add(new Callable<Long>() {
public Long call() {
Date before = new Date();
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port));
}
catch (Throwable e) {
e.printStackTrace();
}
Date after = new Date();
return after.getTime() - before.getTime();
}
});
System.out.println("Invoking");
List<Future<Long>> results = executor.invokeAll(tasks);
System.out.println("Invoked");
for (Future<Long> future : results) {
System.out.println(future.get());
}
executor.shutdown();
}
private static void usage() {
System.out.println("Usage: prog <threads> <url/IP Port>");
System.out.println("Examples:");
System.out.println(" prog tcp 10 127.0.0.1 2000");
}
}
Run Code Online (Sandbox Code Playgroud)
更新 - 如果在运行测试程序之前清除相关的ARP条目,问题将一致地重现.我已经尝试调整TCP重传超时,但这没有帮助.此外,我们将此程序移植到.Net,但问题仍然存在.
更新2 - 3秒是从RFC 1122创建新连接的指定延迟.我仍然不完全理解为什么这里有重传,它应该由MAC层处理.另外,我们使用netcat重现了这个问题,因此它与java无关.
我还没有从这次讨论中找到真正的答案。我想出的最好的理论是:
我尝试过在 Windows 7 中调整超时,但没有成功。如果有人可以重现该问题并提供解决方法,我将非常有帮助。另外,如果有人有更多关于为什么这种现象只发生在多线程中的详细信息,那么听听会很有趣。
我会尝试接受这个答案,因为我认为任何答案都没有提供真正的解释(请参阅meta 上的讨论)。