Trop de TIME_WAIT connexions, “Ne peut pas assigner une adresse demandée”
J'ai une petite application web qui ouvre une connexion socket TCP, émet une commande, de lit la réponse, puis ferme la connexion pour chaque demande à un certain point de terminaison REST.
J'ai commencé les essais en charge le système d'extrémité à l'aide d'Apache JMeter et je suis en remarquant qu'après l'exécution pendant un certain temps, je commence à voir les erreurs du type "Impossible d'assigner une adresse demandée", le code d'ouverture de cette connexion est:
def lookup(word: String): Option[String] = {
try {
val socket = new Socket(InetAddress.getByName("localhost"), 2222)
val out = new PrintStream(socket.getOutputStream)
val reader = new BufferedReader(new InputStreamReader(socket.getInputStream, "utf8"))
out.println("lookup " + word)
out.flush()
var curr = reader.readLine()
var response = ""
while (!curr.contains("SUCC") && !curr.contains("FAIL")) {
response += curr + "\n"
curr = reader.readLine()
}
socket.close()
curr match {
case code if code.contains(SUCCESS_CODE) => {
Some(response)
}
case _ => None
}
}
catch {
case e: Exception => println("Got an exception "+ e.getMessage); None
}
}
Quand je lance la commande netstat je vois aussi beaucoup de la suite de TIME_WAIT connexion statues, ce qui implique, pour moi, que je suis à court de ports dans l'espace éphémère.
tcp6 0 0 localhost:54646 localhost:2222 TIME_WAIT
tcp6 0 0 localhost:54638 localhost:2222 TIME_WAIT
tcp6 0 0 localhost:54790 localhost:2222 TIME_WAIT
tcp6 0 0 localhost:54882 localhost:2222 TIME_WAIT
Je me demande quelle solution est la meilleure pour cette question. Ma pensée est que la création d'un pool de connexion où les connexions à ce service qui s'exécute sur le port 2222
peuvent être réutilisés par les différentes requêtes HTTP, plutôt que de créer de nouvelles demandes à chaque fois. Est-ce un bon moyen de résoudre le problème et de faire la demande à l'échelle de mieux? Il semble comme beaucoup de frais généraux à introduire et certainement fait ma demande plus compliqué.
Existe-il d'autres solutions pour aider cette application à l'échelle et de surmonter ce port problème que je ne vois pas? Mon application web est en cours d'exécution dans une VM Ubuntu linux.
Aussi stackoverflow.com/questions/16014627/... et quelques millions d' 🙂 d'autres questions connexes - voir la liste sur le RHS ->
OriginalL'auteur jcm | 2014-09-24
Vous devez vous connecter pour publier un commentaire.
Oui, la création d'un pool de connexions est une bonne solution. Toutefois, une solution plus simple est d'avoir le serveur fermer les connexions, plutôt que sur le client. Dans ce cas, le serveur de sockets, plutôt que du client, de l'état TIME_WAIT, de sorte que le client ne serait pas à court de ports. Sur le côté serveur, les connexions dans l'état TIME_WAIT ne serait pas faire exécuter le serveur de ports, car ils utilisent tous le même port local.
À assurez-vous que la connexion est fermée par le serveur, vous avez besoin de lire à partir de la prise (sur le client) jusqu'à ce que vous atteignez la fin-de-fichier d'état. En ce moment, il est sûr de fermer le socket sur le côté client parce que le serveur a fermé déjà. Bien sûr, vous devez vous assurer que le serveur va fermer le socket, plutôt que, disons, en attente d'une nouvelle demande.
Sinon, si vous avez accès à la racine, il y a quelques sysctl options que vous pouvez modifier:
net.ipv4.ip_local_port_range
– plage de ports éphémères. L'augmenter pour faire plus de ports disponibles pour les connexions sortantes.net.ipv4.tcp_tw_recycle
– permettre un recyclage plus rapide des connexions dans l'état TIME_WAIT.net.ipv4.tcp_tw_reuse
– permettre la réutilisation des connexions dans l'état TIME_WAIT. Pas recommandé.Voir les pages de man
ip(7)
ettcp(7)
pour plus d'informations.Vous pouvez essayer d'envoyer certaines données non valides pour le serveur fermer sa connexion. J'ai aussi ajouté quelques sysctl options pour la réponse, mais vous avez besoin d'un accès root pour changer.
le guide de réglage de @ gatling.io/docs/actuel/général/opérations permet de résoudre ce problème et donne le détail des commandes à exécuter. L'ajout de ce commentaire, le lien s'aligne avec la réponse ci-dessus par @abacabadabacaba. merci
OriginalL'auteur abacabadabacaba
Connexion de la mise en commun permettra de résoudre ce problème pour vous.
Vous avez également mentionné que "RESTE" dans la question que les gens associent souvent avec RESTful HTTP/Web Services. Bien sûr, qui n'a pas à être le cas, comme dans votre exemple.
Je n'ai rien dit sur HTTP. Je ne sais pas ce qui vous fait penser que HTTP est le protocole uniquement dans le monde, vous pouvez utiliser la connexion de la mise en commun.
OriginalL'auteur user207421