J'ai une application qui manque de descripteurs de fichier, apparemment en ouvrant des sockets, mais je ne peux pas savoir exactement ce que font ces prises. 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 in/proc/$ pid/fd comme
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 dans netstat -a
.
Quelles sont ces sockets et comment puis-je découvrir ce qu'ils font?
Editer : J'ai essayé de courir grep $SOCKET /proc/net
, comme recommandé dans la section LSOF FAQ , où $ socket est par exemple 263746679, mais cela n'a donné aucun résultat.
En arrière-plan, l'application est un conteneur pour plusieurs tâches qui, entre autres, effectuent des appels réseau. J'ai besoin de singler celui qui va Berserk, mais jusqu'à ce que je découvre que ces prises communiquent avec, je suis coincé.
En utilisant Python, j'ai rencontré le même problème sur les sockets SSL:
La solution consistait à déballer la couche SSL avant la fermeture:
Cela ferme les sockets correctement dans mon application.
La première chose que je ferais est d'augmenter si votre limite de descripteur de fichier:
~# vi /etc/sysctl.conf
fs.file-max = 331287
Ensuite, je vous assurerais que votre système est à jour, cela inclut toutes les bibliothèques et serveurs. Il est possible que votre Java Application Server soit obsolète (si vous utilisez une). C'est également une possibilité que votre serveur d'applications soit mal configuré, vous devez consulter votre fichier de configuration et réduire votre connectionTimeout
et/ou votre maxKeepAliveRequests
(Je ne sais pas quel serveur d'applications votre utilisation ou si vous utilisez un du tout ...).
Je ne suis pas sûr de ce que cette application fait, mais si vous ne pensez pas que cela nécessite des dizaines de milliers de sockets, c'est presque certainement un "Fuite de fichier de descripteur" dans votre Java Application. Vous devrez peut-être envoyer un rapport de bogue au fournisseur. Dans ce rapport de bogue, vous devez inclure des informations sur la recréer.
Voici quelques moyens de déboguer la question.
Wireshark (ou Twirshark pour la CLI) est le meilleur outil pour voir comment ces prises sont utilisées. Wireshark vous donnera une rupture du type de trafic étant jeté sur le fil. Il est probable que les premières connexions réussiront, puis il frappera la limite de descripteur de fichier. Une fois que la limite de descripteur de fichier est touchée, alors Wireshark ne va pas venir sur quoi que ce soit (et NetStat est NetStat, mais cela aidera à réduire la question. Il y a peut-être cas de cas où beaucoup de synchronisation sortante sont envoyées, mais aucun Syn/ACKS n'est reçu, de nombreuses connexions TCP ne sont que bloquées dans l'état Syn_Wait.
Si vous avez accès au code source et que vous connaissez le type de sockets créé (tels que l'utilisation de la strace ou simplement sur le code), vous pouvez ouvrir le projet dans Eclipse (ou un autre IDE) et définir un point de rupture à la fonction que crée ces prises. Lorsque le point d'arrêt est touché, vous pouvez regarder la trace de la pile. Cette fuite de descripteur de fichier peut-être une simple boucle infinie ou peut-être la valeur du délai d'attente de socket est trop grande. Une autre possibilité est que le =Java application ne fait pas de socket.close()
pour nettoyer les connexions. Faire une fermeture est couramment faite dans le bloc finely
d'un try/catch
(Oui Une prise doit toujours avoir un essai/attrape in Java ou il ne construira pas :). À la fin de la journée, il est probable que le = Java application ne manipule pas correctement son IOException.