Forum Linux.redhat Raisons susceptibles du déclenchement d'OOM killer

Posté par  .
Étiquettes : aucune
0
16
nov.
2006
Bonjour,
Je ne suis pas expert Linux et Red Hat.
J'aurais cependant une question suite à un problème qui m'a été remonté.
OOM killer se déclenche sur un serveur d'application RHEL 4.0 32 bits sur lequel est également installé JBoss 4.0.3 SP1.
Est ce que le déclenchement d'OOM killer peut être expliqué par l'utilisation du filesystem OCSF2? (En effet, les données aplicatives sont écrites dans un SGBD Oracle)Ou est ce que cette explication est erronée?
Quels peuvent etre les autres raisons expliquant le déclenchement d'OOM killer (mauvaise gestion mémoire dans les programmes développés coté serveur d'application)?
Merci d'avance de vos lumières
  • # La honte du noyau

    Posté par  . Évalué à 8.

    OOM killer (Out-Of-Memory Killer) est une fonctionnalite du kernel qui se declenche quand il n'y a plus aucune memoire disponible sur le systeme. Les operations d'allocation memoire ont sature la memoire physique, puis le swap, puis il ne reste plus de place pour allouer encore. A ce moment-la, le kernel prend son courage a deux mains et decide qu'il doit y avoir une application qui est decidement trop gourmande en memoire et qu'elle a ete donc forcement mal programmee et ne merite plus de vivre. Il observe les processes qui sont les plus gourmands en consommation memoire et les tue jusqu'a ce que le systeme recouvre assez de ressources pour continuer a fonctionner.

    Dans ton cas, tu as sans doute une application qui est partie en vrille en allouant de nouveaux objets en pagaille sans les liberer. Avec les infos que tu donnes je pencherais pour un probleme Java (JBoss). En aucun cas un filesystem ne peut declencher directement l'intrepide OOM killer. Si tu as de la chance, OOM killer decidera de tuer precisement l'application qui pose des problemes, mais rien n'empeche OOM killer de dezinguer ton serveur X ou bien ta session eclipse dans laquelle tu travailles depuis 2 jours sans sauvegardes. C'est lui qui choisit, pas toi.

    Dans le detail: OOM killer fait d'une machine Linux une veritable bombe a retardement pour toutes les applis qui ont besoin du maximum de memoire qu'elles peuvent allouer. Pour les applis desktop c'est encore acceptable mais pour du deploye industriellement c'est critiquement grave.

    Linux est (a priori) le seul Unix qui vienne avec cet infame OOM killer. La raison profonde derriere ce patch est le fait que le kernel Linux s'amuse a promettre bien plus de memoire qu'il ne peut en offrir (memory overcommitment). Application: ecrire une boucle qui alloue des paquets de 1 Meg a la fois et regarder combien on peut en allouer (mon noyau me promet jusqu'a 4 Gb sur une machine qui possede 512 Mb de RAM + 512 Mb de swap). Deuxieme essai: allouer les blocs en boucle jusqu'a ce que malloc retourne NULL, puis remplir de zero les zones allouees une par une. La RAM se remplit, puis le swap, puis apres c'est le bonheur: soit le noyau plante, soit OOM killer intervient et (parfois) tue d'autres processes vitaux du systeme, ce qui finit en desastre complet.

    Pourquoi le noyau s'amuse-t-il donc a promettre plus de memoire que ce dont il dispose? Apparemment c'est du a l'implementation de fork() qui commence par repliquer le process qui fait cet appel, incluant une copie complete de sa memoire, ce qui prend du temps. Generalement un process qui fork() fait immediatement un exec derriere, ce qui rend inutile la perte de temps de recopie de memoire. Le noyau prefere promettre a fork() de la memoire dont il ne se servira de toutes facons pas.

    Si ce comportement vous inquiete vous pouvez desactiver le memory overcommitment en manipulant des flags dans /proc/sys/vm (suivant la version de kernel). Attention alors: le systeme ralentit considerablement.
    • [^] # Re: La honte du noyau

      Posté par  . Évalué à 1.

      Merci beaucoup pour ces explications détaillées.
    • [^] # Fuite mémoire JBoss

      Posté par  . Évalué à 3.

      Je confirme qu'il ne faut pas chercher une explication niveau système, hardware ou autre lié à Red Hat.

      Il s'agit très probablement bel et bien du serveur d'appli qui est fautif.

      Une de vos applis sous JBoss provoque des fuites mémoires.

      D'ailleurs si vous monitorez la mémoire prise par JBoss (par un simple top par exemple), vous verrez certainement la mémoire prise par celui allant en augmentant au fil du temps et de l'utilisation de l'appli fautive.
      Et effectivement, une fois la RAM pleine, le Swap sera attaqué à son tour par JBoss sans jamais diminuer jusqu'à atteindre sa limite.
      A ce moment, le kernel ne se posera plus de questions pour préserver la survie du système et fera le ménage en killant ce qui monopolise la mémoire.

      Donc c'est bien au niveau des applis java sous JBoss qu'il faut investiguer.


      Maintenant il ne s'agit pas nécessairement d'un problème d'objets mal gérés dont le Garbage Collector n'arriverait pas à se débarrasser. Car dans ce cas, théoriquement, vous finiriez par avoir des OutOfMemory Exceptions, et jamais ça ne dépasserait le cadre de la mémoire allouée à la JVM. Tout ce que vous auriez dans ces cas la, c'est un comportement instable de vos applis.


      Le problème est donc plus "profond" et plus vicieux, car de la mémoire hors JVM est allouée et n'est jamais libérée.

      Ca n'est pas particulièrement facile à diagnostiquer (bon courage d'ailleurs) mais ça peut être lié au système tout de même notamment dans la façon dont Java va interagir avec.

      En gros, voyez si vos problèmes ne sont pas liés avec les points suivants (en vrac):
      - mauvaise gestion de stream (ex: un InputStream ou OutputStream ouvert mais non fermé)
      - par extension mauvaise manipulation de fichiers (ex: dans le cas d'un upload d'un fichier envoyé par un formulaire Multipart/form)
      - mauvaise gestion des transactions avec la base de données (resultsets ouverts mais non fermés).
      - ça peut dépendre encore du type d'interaction que vous avez avec ce File System OCSF2.
      - Enfin essayez de mettre à jour vos librairies (.jar) voir si le problème se produit toujours.
    • [^] # Re: La honte du noyau

      Posté par  . Évalué à 3.

      vous pouvez desactiver le memory overcommitment [...]
      Voir "man proc" pour les valeurs à mettre effectivement dans /proc/sys/vm/overcommit_memory: (dépend si on a un 2.4 ou un 2.6)

      /proc/sys/vm/overcommit_memory
      This file contains the kernel virtual memory accounting mode.
      Values are:
      0: heuristic overcommit (this is the default)
      1: always overcommit, never check
      2: always check, never overcommit

      ou modifier la valeur dans /proc/sys/vm/overcommit_ratio


      Voir aussi /proc/meminfo, il y a des entrées sur l'utilisation de mémoire "overcommitée" expliquées dans http://www.redhat.com/advice/tips/meminfo.html
      • [^] # Re: La honte du noyau

        Posté par  . Évalué à 1.

        Merci daggett pour ces precisions!

        Dans mon experience, Linux est un systeme extremement peu fiable pour tout ce qui concerne la gestion de la memoire aux limites. Quand on a des processes qui ont besoin du maximum de RAM qu'ils peuvent allouer, les Unix standards nous ont habitue a utiliser malloc() et lui faire confiance pour retourner NULL quand il n'y a plus de ressources disponibles. Ce contrat n'est pas respecte sous Linux et ce n'est pas la faute de malloc(), mais bien celle du noyau.

        Sur des programmes qui peuvent etre mission-critical (francais?), un tel comportement n'est pas acceptable. La seule facon de s'en sortir est de determiner soi-meme la quantite de memoire disponible a priori sur la machine locale, de surcharger les allocations memoire avec un compteur et d'arreter d'allouer quand le compteur indique une limite atteinte. Les nombreuses discussions qui ont eu lieu avec les developpeurs en charge de la gestion memoire sous Linux se sont terminees en queue de poisson.

        Ceci dit, il est rare d'avoir a ecrire des programmes qui ont besoin forcement d'allouer le maximum de memoire disponible dans un environnement critique. Pour la quasi totalite des applications qui tournent sur des desktops, les points decrits ici ne s'appliquent pas. Dans le cas precisement evoque ici, le kernel s'est retrouve aux limites a cause d'une faute de programmation dans une appli Java. Pas de panique donc! Les gens qui ont l'habitude de pousser Linux a ses limites en gestion de memoire doivent juste etre conscients des limitations induites par l'overcommitment.
        • [^] # Re: La honte du noyau

          Posté par  (Mastodon) . Évalué à 1.

          La seule facon de s'en sortir est de determiner soi-meme la quantite de memoire disponible a priori sur la machine locale,

          Plus judicieux il serait, à mon avis, de déterminer la mémoire dont a besoin l'application, et de configurer la machine en conséquence.

          de surcharger les allocations memoire avec un compteur

          Plus simplement, peut-être voir si tu ne peux pas protéger ton système avec des ulimit mûrement réfléchis...
        • [^] # Re: La honte du noyau

          Posté par  . Évalué à 2.

          Je suis loin d'être un spécialiste, donc j'ai peut-être une mauvaise appréciation de la situation, mais à quoi ça peut bien servir de faire survivre une appli à tout prix dans un système qui, de toutes manières, est complètement mort? Si la swap est assez grande, le taux de "ramage" de la machine va la rendre complètement inutilisable bien avant le déclenchement d'un éventuel OOM killer (j'ai l'expérience de serveurs virtuellement morts -- pas de réponse au ping, 30 minutes pour afficher le "k" de "kill" sur une console précédemment ouverte) à la suite d'une fuite de mémoire dans une application (oui, ok, c'est moi qui l'avais codée...). Dans ce cas, le process qui est la cause du bouzin n'a aucune chance d'aboutir dans un délai raisonnable, et c'est quand même mieux que le noyau fasse le ménage tout seul pour assurer sa survie plutôt que de marcher vers la mort comme un abruti...
          • [^] # Re: La honte du noyau

            Posté par  . Évalué à 3.

            ce qui est reproché au système c'est de prétendre d'avoir de la place alors qu'il en a plus...
            Quand un malloc te renvoie NULL, tu peux agir en conséquence ( ie vider le cache de ton appli, déclencher un ménage général, fermer tout ce qui n'a pas été utilisé depuis un certain temps, sauver les paramètres de l'appli et quitter.... )
            Quand le malloc te donne une adresse mémoire, et que quand tu l'utilise ton process est tué sur place, c'est moyen.

            Cependant, c'est un comportement réglable, donc pas ou peu gênant à mon gout, par ailleurs, ulimit permet justement d'éviter les problèmes :)

            Il ne faut pas décorner les boeufs avant d'avoir semé le vent

            • [^] # Re: La honte du noyau

              Posté par  . Évalué à 1.

              ulimit est un reglage de parametres sous bash, c'est plutot du domaine du desktop. Sa valeur depend entierement de l'utilisateur qui lance l'application, alors que cette valeur devrait etre fixee par l'application elle-meme en accord avec les ressources disponibles. Ca peut resoudre le probleme pour un utilisateur desktop soucieux de ne pas planter sa machine par un memory leak au cours du developpement, c'est tres difficile a regler system-wide.

              Quand malloc retourne NULL on peut faire encore beaucoup de choses comme par exemple mapper des espaces disque pour creer son propre swap. Une appli peut aussi avoir envie de profiter du maximum d'espace memoire disponible pour accelerer ses calculs le plus possible. Le probleme de l'overcommitment c'est qu'on ne peut pas compter sur le systeme pour nous dire a un instant T si la prochaine allocation pourra se faire ou bien si elle plantera le systeme.

              Pour l'histoire: la discussion qui a precede l'existence de ce patch date de 98. Voir par exemple:


              http://lkml.org/lkml/1998/8/14/77

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.