Java lente prise.connect()

Ci-dessous est le code source d'un client et un serveur.
Le client se connecte (simultanément) pour le serveur et immédiatement ferme la connexion.
Lorsque tous les threads sont fait, il attend 2 minutes et se connecte à nouveau.
J'ai des doutes sur le fait que parfois, un simple connecter besoins autour de 3 secondes!
La plupart du temps a se connecter a juste besoin d'environ 0-32ms.

Ici un exemple de résultat de la part du client:

...
Connect 23 [ms]: 16
Connect 22 [ms]: 32
Connect 21 [ms]: 32
Connect 15 [ms]: 32
Connect 14 [ms]: 16
Connect 13 [ms]: 16
Connect 11 [ms]: 32
Connect 25 [ms]: 3016

Cela ne semble se produire si le client et le serveur sont sur des hôtes différents.
Windows et linux comparable comportement
Java 1.6.23

pour démarrer le serveur 2 paramètres sont nécessaires:
[port] [taille du pool de threads]

pour démarrer le client 3 paramètres sont nécessaires:
[accueil] [port] [taille du pool de threads]

pour l'exemple j'ai utilisé 150 taille du pool de threads pour le serveur et le 25 taille du pool de threads pour le client.

Quelqu'un peut-il expliquer ce comportement?

----- serveur -----

package de.test.server;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerApp {
public static void main(String[] args) throws IOException {
System.out.println("server running...");
final int port = Integer.parseInt(args[0]);
final int threads = Integer.parseInt(args[1]);
final ExecutorService executorService = Executors
.newFixedThreadPool(threads);
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
final Socket clientSocket = serverSocket.accept();
executorService.execute(new Runnable() {
@Override
public void run() {
try {
InputStream is = clientSocket.getInputStream();
int read = is.read();
if (read != -1) {
System.out.println("should not happen");
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
close(clientSocket);
System.out.println("connection closed");
}
}
private void close(final Socket connection) {
try {
connection.close();
} catch (IOException e1) {
throw new RuntimeException(e1);
}
};
});
}
}
}

----- client -----

package de.test.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
public class ConnectApp {
public static void main(String[] args) throws InterruptedException {
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int THREAD_COUNT = Integer.parseInt(args[2]);
final ExecutorService executorService = Executors
.newFixedThreadPool(THREAD_COUNT);
final AtomicLong threadCounter = new AtomicLong(0);
while (true) {
final CountDownLatch doneSignal = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
Socket socket = null;
try {
long start = System.currentTimeMillis();
socket = new Socket();
socket.setTcpNoDelay(true);
socket.connect(new InetSocketAddress(host, port));
System.out.println(socket.getTcpNoDelay());
long stop = System.currentTimeMillis();
System.out.println("Connect "
+ threadCounter.incrementAndGet() + " [ms]: "
+ (stop - start));
} catch (UnknownHostException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
close(socket);
doneSignal.countDown();
}
}
private void close(Socket socket) {
try {
if (socket != null)
socket.close();
} catch (IOException e1) {
throw new RuntimeException(e1);
}
}
});
}
doneSignal.await();
System.out.println("Waiting 2 minutes...");
Thread.sleep(1000 * 60 * 2);
}
}
}
Avez-vous vérifier vos temps de ping du client?
Cela pourrait être une GC pause?
Vous avez une très subtile bug dans vos applications. Lors de l'inspection que j'avais un doute c'est la cause du comportement que nous observons, mais techniquement ExecutorService.execute(Runnable) peut, à sa discrétion, à l'exécution du thread appelant. Ce serait de la transformer en un appel bloquant. Une plus correct d'un appel serait probablement executorService.submit(new Runnable().... Encore une fois, je doute que c'est la cause puisque vous êtes à l'aide d'un ThreadPoolExecutor mais c'est probablement la peine de la fixation de toute façon.
En fait sur plus d'une inspection, il ressemble à ceci notamment la mise en œuvre de ExecutorService juste délégués à execute de toute façon donc c'est vraiment probablement pas un problème.

OriginalL'auteur coder | 2011-01-25