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);
}
}
}
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
Vous devez vous connecter pour publier un commentaire.
Toutes vos prises de courant essayez de vous connecter à la fois. Depuis qu'ils sont en train d'essayer de se connecter sur le même thread unique serveur, on va accepter, 50 (par défaut) sera dans le carnet de commandes et le reset ne peut pas se connecter ou à attendre un temps particulièrement long.
Je vous propose d'essayer de 40 ms espacement entre tentez de vous connecter pour voir si ce n'est le problème.
BTW: vous appelez seulement
threadCounter.incrementAndGet()
alors, pourquoi est-ce qu'il va en haut et en bas? Vous pouvez simplement utiliserLe serveur passe la plupart de son temps à accepter des connexions, il n'y a qu'un seul thread faisant cela, si votre test est effictively monothread. (Il y a toujours plusieurs threads s'exécutant dans une machine virtuelle java, ce n'est pas tous les JVM applications multi-thread à mon humble avis)
sûr que j'ai suivi.Il y a un thread qui est toujours en attente pour les nouvelles connexions. Une fois une connexion, il passe à la prise secteur à l'autre fil de la bande de roulement de la piscine et le thread principal attend pour de nouvelles connexions.N'est-ce pas classique serveur multithread de programmation?
Votre suggestion de retard aide il n'y a pas de gros 3s blocage intervall plus. Mais Qui ou quoi est responsable de ce très gros blocage de l'intervalle. Est-ce le serveur, est-il le client? est-ce une sorte de protection contre les attaques DoS? À partir de l'OS, TCP/IP,...? Un collègue a réécrit ce client/serveur en C, et les résultats sont les mêmes.
Il est plus probable que le serveur ne va pas prendre un grand nombre de non-clients admis sans un certain retard. Le problème, c'est que votre comportement est peu réaliste et susceptible de confondre tout de réglage des performances de l'OS.
OriginalL'auteur Peter Lawrey