(见
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连接池.