J'ai une application qui manque de descripteurs de fichiers, apparemment en ouvrant des sockets, mais je ne peux pas savoir exactement ce que font ces sockets. Ceux-ci apparaissent dans la sortie lsof comme
java 9689 appuser 1010u sock 0,5 263746675 can't identify protocol
java 9689 appuser 1011u sock 0,5 263746676 can't identify protocol
java 9689 appuser 1012u sock 0,5 263746677 can't identify protocol
java 9689 appuser 1014u sock 0,5 263746678 can't identify protocol
java 9689 appuser 1015u sock 0,5 263746679 can't identify protocol
java 9689 appuser 1016u sock 0,5 263746681 can't identify protocol
et dans / proc / $ PID / fd as
lrwx------ 1 appuser appuser 64 Jun 23 11:49 990 -> socket:[263732085]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 991 -> socket:[263732086]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 992 -> socket:[263735307]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 993 -> socket:[263732088]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 995 -> socket:[263735308]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 996 -> socket:[263735309]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 997 -> socket:[263745434]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 998 -> socket:[263745435]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 999 -> socket:[263745436]
mais il n'y a pas de sortie similaire en netstat -a
.
Que sont ces prises et comment savoir ce qu'elles font?
Edit : J'ai essayé de courir grep $SOCKET /proc/net
, comme recommandé dans la FAQ lsof , où $ SOCKET est par exemple 263746679, mais cela n'a donné aucun résultat non plus.
En arrière-plan, l'application est un conteneur pour plusieurs tâches qui, entre autres, effectuent des appels réseau. Je dois distinguer celle qui devient folle, mais jusqu'à ce que je découvre avec qui ces prises communiquent, je suis coincé.
Réponses:
Cela peut se produire si vous créez un socket, mais ne vous connectez jamais () ou ne liez pas () avec lui. Le mieux est peut-être de mettre en forme (-fF) l'application, puis de faire un croisement avec la sortie de lsof pour déterminer les sockets à l'origine du problème. Comme méthode bonus de débogage: si vous encapsulez vos appels de socket avec des informations de débogage et les écrivez dans / dev / null, ils apparaîtront en strace sans vous donner des fichiers journaux hilarants.
la source
En utilisant Python, j'ai rencontré le même problème sur les sockets SSL:
La solution était de déballer la couche SSL avant de fermer:
Cela ferme correctement les sockets dans mon application.
la source
La première chose que je ferais est d'augmenter la limite de descripteur de fichier:
Ensuite, je m'assurerais que votre système est à jour, cela inclut toutes les bibliothèques et tous les serveurs. Il est possible que votre serveur d'applications Java soit obsolète (si vous en utilisez un). Il est également possible que votre serveur d'applications soit mal configuré, vous devriez regarder votre fichier de configuration et baisser votre
connectionTimeout
et / ou votremaxKeepAliveRequests
(je ne sais pas quel serveur d'applications vous utilisez ou si vous en utilisez un du tout ...).Je ne suis pas sûr de ce que fait cette application, mais si vous ne pensez pas qu'elle nécessite des dizaines de milliers de sockets, il s'agit presque certainement d'une "fuite de descripteur de fichier" dans votre application Java. Vous devrez peut-être envoyer un rapport de bogue au fournisseur. Dans ce rapport de bogue, vous devez inclure des informations sur la façon de recréer le problème.
Voici quelques façons de déboguer le problème.
Wireshark (ou twireshark pour le cli) est le meilleur outil pour voir comment ces sockets sont utilisées. Wireshark vous donnera une ventilation du type de trafic jeté sur le câble. Il est probable que les premières connexions réussissent, puis il atteindra la limite de descripteur de fichier. Une fois que la limite de descripteur de fichier est atteinte, Wireshark ne va rien reprendre (et plus net est netstat d'ailleurs), mais cela aidera à réduire le problème. Il peut y avoir des cas où beaucoup de SYN sortants sont envoyés, mais aucun SYN / ACK n'est reçu, donc beaucoup de connexions TCP sont simplement bloquées dans l'état SYN_WAIT.
Si vous avez accès au code source et que vous connaissez le type de sockets en cours de création (comme utiliser strace ou simplement rechercher le code), vous pouvez ouvrir le projet dans Eclipse (ou un autre IDE) et définir un point d'arrêt à la fonction qui crée ces sockets. Lorsque le point d'arrêt est atteint, vous pouvez regarder la trace de la pile. Cette fuite de descripteur de fichier peut être une simple boucle infinie ou la valeur du délai d'expiration du socket est trop grande. Une autre possibilité est que l'application java ne
socket.close()
nettoie pas les connexions. Faire une fermeture se fait généralement dans unfinely
bloc detry/catch
(Oui, un socket doit toujours avoir un try / catch en Java ou il ne se construira pas :). À la fin de la journée, il est probable que l'application Java ne gère pas correctement ses IOExceptions.la source