(见
this question in ServerFault)
我有一个使用Socket的Java客户机打开到同一台机器的并发连接.我目睹一个请求完成的速度非常快,但其他请求的延迟为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"); } }
更新 – 如果在运行测试程序之前清除相关ARP条目,则问题会一再重现.我试过调整TCP retransmission timeout,但这没有帮助.此外,我们将该程序移植到.Net,但问题仍然发生.
更新2 – 3秒是从RFC 1122创建新连接的指定延迟.我仍然不完全明白为什么这里有一个重传,它应该由MAC层处理.此外,我们使用netcat重现了这个问题,所以与java无关.
解决方法
看起来您使用单个底层的HTTP连接.因此,在HttpURLConnection的InputStream调用close()之前,其他请求无法完成,i.即在处理响应之前.
或者你应该使用一个HTTP连接池.