9
votes

Trop de poignées de fichier ouverts

Je travaille sur une énorme application Java héritée, avec beaucoup de choses manuscrites, ce qui permet de laisser un framework gérer.

Le problème que je suis confronté en ce moment est que nous manquons de poignées de fichier sur notre serveur Solaris. J'aimerais savoir quelle est la meilleure façon de suivre les poignées de fichier ouverts? Où regarder et ce qui peut causer des poignées de fichier ouverts à s'épuiser?

Je ne peux pas déboguer la demande sous Solaris, uniquement sur mon environnement de développement Windows. Est même raisonnable d'analyser les poignées de fichier ouverte sous Windows?


1 commentaires

avec un PID LSOF -P, l'entrée la plus courante est la suivante: Java 19157 dev 131u Unix 105,98572 0T829 55050244 / Appareils / Pseudo / TL @ 0: Ticots -> (SocketPair: 0x1810C) (0x300199eed50) Toute idée de ce que cela signifie Et comment je peux le combattre?


12 Réponses :


0
votes

Cela pourrait certainement vous donner une idée. Étant donné que c'est Java, la mécanique du fichier ouvert / fermeture doit être implémentée de la même manière (à moins que l'une des JVMS ne soit mal implémentée). Je recommanderais d'utiliser moniteur de fichier sous Windows.


0 commentaires

1
votes

Je commencerais par demander à mon sysadmin d'obtenir une liste de descripteurs de fichiers ouverts pour le processus. Différents systèmes le font de différentes manières: Linux, par exemple, possède le répertoire / proc / pid / fd . Je me souviens que Solaris a une commande (peut-être Pfiles ?) Cela fera la même chose - votre Sysadmin devrait le savoir.

Cependant, si vous ne voyez pas beaucoup de références au même fichier, une liste FD ne va pas vous aider. Si c'est un processus de serveur, il dispose probablement de nombreux fichiers (et sockets) ouverts pour une raison. Le seul moyen de résoudre le problème est d'ajuster la limite du système sur les fichiers ouverts - vous pouvez également vérifier la limite par utilisateur avec ulimit , mais dans la plupart des installations actuelles qui équivalent à la limite du système.


0 commentaires

7
votes

sur Windows Vous pouvez consulter Open File Gingles à l'aide de Process Explorer:

http://technet.microsoft.com/en-us/sysinternals/ BB896653.aspx

sur Solaris, vous pouvez utiliser "LSOF" pour surveiller les poignées du fichier ouvert


2 commentaires

Merci! J'ai utilisé LSOF, malheureusement, il y a beaucoup de choses qui se passent et je ne sais pas vraiment comment réduire les résultats de LSOF à ce qui est pertinent et ce qui n'est pas intéressant.


Le résultat de Windows ne doit pas être extrapolé les systèmes * Nix. Ils ont un mécanisme différent des fichiers d'ouverture.



1
votes

Pas une réponse directe à votre question, mais ces problèmes pourraient être le résultat de la libération des ressources de fichiers incorrectement dans votre code hérité. Par exemple, si vous travaillez avec les classes FileOutPutStream, assurez-vous que les méthodes de fermeture sont appelées enfin de bloc, comme dans cet exemple: xxx


2 commentaires

Ce qu'il a dit. On dirait que les poignées de fichier ne sont jamais libérées.


Merci pour les conseils généraux, mais j'ai cherché toutes les occurrences de Java.IO. * Et nous sommes assurés qu'ils sont dans un bloc de try-catch-enfin.



8
votes

Une bonne chose que j'ai trouvée pour suivre les poignées de fichier non clothes est Findbugs:

http://findbugs.sourceforge.net/

Il vérifie beaucoup de choses, mais l'une des plus utiles est la ressource ouverte / proche des opérations. C'est un programme d'analyse statique qui fonctionne sur votre code source et il est également disponible en tant que plug-in Eclipse.


3 commentaires

En tant que témoignage personnel, j'ai eu un problème similaire à celui que l'OP avait (mon application jetait des exceptions parce qu'elle ne pouvait plus ouvrir de fichiers car j'avais trop de descripteurs de fichiers ouverts). L'exécution du code via Findbugs a aidé à identifier tous les endroits où les fichiers n'étaient pas fermés. Problème résolu!


Oui, il m'a une fois aidé à trouver une série de places où de près () n'avait pas été appelée dans un blocage approprié enfin.


Bien que cela ne résoudait pas mon problème directement, c'était un excellent indice!



2
votes

Pour répondre à la deuxième partie de la question:

Que peut causer des poignées de fichier ouverts à s'épuiser?

ouvrir beaucoup de fichiers, évidemment, et ne pas les fermer.

Le scénario le plus simple est que les références à tous les objets contiennent les poignées natives (par exemple, fichierInputtream ) avant d'être fermé, ce qui signifie que les fichiers restent ouverts jusqu'à ce que les objets soient finalisés.

L'autre option est que les objets sont stockés quelque part et non fermés. Un dépotoir de tas pourrait être capable de vous dire ce qui persiste où ( jmap et JHAT est inclus dans la JDK, ou vous pouvez utiliser Jvisalvm si vous voulez une interface graphique). Vous êtes probablement intéressé à chercher des objets possédant FileDeScriptor s.


0 commentaires

2
votes

Ce petit script aidez-moi à garder les yeux sur le nombre de fichiers ouverts lorsque j'ai besoin d'un compte IC test. Si elle a été utilisée sur Linux, alors pour Solaris, vous devez le corriger (peut-être :))

#!/bin/bash
COUNTER=0
HOW_MANY=0
MAX=0
# do not take care about COUNTER - just flag, shown should we continie or not
while [ $COUNTER -lt 10 ]; do
    #run until process with passed pid alive
    if [ -r "/proc/$1" ]; then
        # count, how many files we have
        HOW_MANY=`/usr/sbin/lsof -p $1 | wc -l`
        #output for live monitoring
        echo `date +%H:%M:%S` $HOW_MANY
        # uncomment, if you want to save statistics
        #/usr/sbin/lsof -p $1 > ~/autocount/config_lsof_`echo $HOW_MANY`_`date +%H_%M_%S`.txt

        # look for max value
        if [ $MAX -lt $HOW_MANY ]; then
            let MAX=$HOW_MANY
            echo new max is $MAX
        fi 
        # test every second. if you don`t need so frequenlty test - increase this value
        sleep 1
    else
        echo max count is $MAX
        echo Process was finished
        let COUNTER=11
    fi
done


0 commentaires

2
votes

Cela peut ne pas être pratique dans votre cas, mais ce que j'ai fait une fois lorsque j'ai eu un problème similaire avec les connexions de base de données ouvertes, la fonction "ouverte" a été remplacée par la mienne. (Commodément, j'ai déjà eu cette fonction parce que nous avions écrit notre propre mise en commun de la connexion.) Dans ma fonction, j'ai ensuite ajouté une entrée à une table enregistrant l'ouverture. J'ai fait un appel de trace de pile et j'ai sauvé l'identifiant de l'appelant, avec le temps appelé et j'oublie quoi d'autre. Lorsque la connexion a été publiée, j'ai supprimé l'entrée de la table. Ensuite, j'ai eu un écran où nous pourrions jeter la liste des entrées ouvertes. Vous pouvez ensuite regarder l'horodatage et voir facilement quelles connexions avaient été ouvertes pour des quantités improbables et quelles fonctions avaient fait ces ouvertures.

De cela, nous avons pu retrouver rapidement les fonctions qui ouvrent des connexions et ne les ferment pas.

Si vous avez beaucoup de poignées de fichier ouvertes, les chances sont que vous ne les fermez pas lorsque vous avez terminé quelque part. Vous dites que vous avez vérifié que vous avez vérifié pour essayer / enfin des blocs, mais je soupçonnerais quelque part dans le code que vous avez manqué un mauvais, ou si vous avez une fonction de la main et ne le rend jamais à la finale. Je suppose qu'il est également possible que vous faites vraiment correctement se ferme chaque fois que vous ouvrez un fichier, mais vous ouvrez des centaines de fichiers simultanément. Si tel est le cas, je ne suis pas sûr de ce que vous pouvez faire autre qu'un programme sérieux de la refonte de programme pour manipuler moins de fichiers, ou un programme sérieux de redéressation à la file d'attente de vos accès de fichiers. (À ce stade, j'ajoute l'habituel », sans connaître les détails de votre application, etc.)


0 commentaires

1
votes

Je vérifierais les paramètres de l'environnement sur votre boîte Solaris. Je crois que par défaut, Solaris n'autorise que 256 poignées de fichier par processus. Pour une application de serveur, surtout s'il s'agit d'un serveur dédié, ceci est très faible. Figure 50 ou plus de descripteurs pour ouvrir des pots JRE et Bibliothèque, puis au moins un descripteur pour chaque requête de demande et de base de données entrante, probablement plus, et vous pouvez voir comment cela ne coupe tout simplement pas la moutarde pour un serveur sérieux.

Consultez le fichier / etc / system , pour les valeurs de rlim_fd_cur et rlim_fd_max , pour voir ce que votre système a défini . Ensuite, déterminez si cela est raisonnable (vous pouvez voir combien de descripteurs de fichiers sont ouverts lorsque le serveur s'exécute avec la commande lsof , idéalement avec le paramètre -P [ID de processus].


0 commentaires

2
votes

Sa peine de garder à l'esprit que Open Sockets consommez également des poignées de fichier sur des systèmes UNIX. Il pourrait donc très bien être quelque chose comme une fuite de pool de connexion de base de données (par exemple, les connexions de base de données ouvertes non fermées et renvoyées à la piscine) qui conduit à ce problème - j'ai certainement vu cette erreur avant de causer une fuite de pool de connexion.


0 commentaires

0
votes

Google pour une application appelée filon à partir de System Internals.

BTW, pour suivre cela, vous pourrez peut-être utiliser quelque chose comme LOPEJ pour enregistrer tous les appels ouverts et fermer les fichiers et les journaux où ils se produisent.


0 commentaires

0
votes

Il s'agit d'un modèle de codage qui aide à trouver des ressources décontractées. Il ferme les ressources et se plaint également dans le journal sur le problème.

class
{
    boolean closed = false;
    File file;

    close() {
        closed = true;
        file.close();
    }

    finalize() {
        if (!closed) {
            log error "OI! YOU FORGOT TO CLOSE A FILE!"
        file.close();
    }
}


1 commentaires

C'est vraiment mauvais design à utiliser finaliser () Informit.com/articles .aspx? p = 1216151 & SEQNUM = 7