Bonjour,
je rencontre actuellement un gros soucis avec un de mes serveurs web/postgresql.
Lorsque je lui envoie du trafic (scripts PHP + quelques images), au bout d'un certain temps tous les process PHP meurt à cause d'une erreur "Out of memory". Au même moment, Postgresql log des erreurs "Cannot allocate memory". Et encore au même moment, exim4 log aussi une erreur "Cannot allocate memory" dans le paniclog...
Le plus étrange c'est que via htop je surveille l'utilisation de la mémoire, et il en utilise à peine 4Go sur les 32 dispo, et même en comptant le cache il en reste la moitié de libre. Je précise aussi que Postgresql a 6Go d'alloué, les process PHP ont une limite de 512Mo. D'ailleurs, dans l'erreur le process PHP disait avoir alloué 512Ko, c'est à n'y rien comprendre.
J'ai cherché longuement mais je ne trouve rien de semblable, et depuis que ce matin j'ai vu ce message dans le paniclog de exim4 c'est encore pire, j'avoue que ça me dépasse.
Si quelqu'un a un début d'idée ça m'aiderait beaucoup !
Merci.
# Question bête…
Posté par Nopenope . Évalué à 6.
[^] # Re: Question bête…
Posté par NeoX . Évalué à 4.
[^] # Re: Question bête…
Posté par Old Geek . Évalué à 2.
si le système est installé en 32bits et qu'il reconnait bien les 32Go de ram, c'est que le PAE est bien activé,
la limite des 4Go s'appliquera toujours mais pour chaque processus indépendamment !,
Que te renvoie un simple "free" par exemple ?
[^] # Re: Question bête…
Posté par NeoX . Évalué à 2.
mais que la limite par processus etait toujours de 2Go.
bon ca n'explique pas que PHP plante avec une limite posée à 512Mo
[^] # Re: Question bête…
Posté par neologix . Évalué à 1.
Il existe un patch 2G/2G qui permet au noyau d'utiliser jusqu'à 2G de RAM sans HIGHMEM, mais n'est pas couramment utilisé.
Il exist(ait ?) aussi un split 4G/4G qui permettait d'utiliser jusqu'à 4G de mémoire, mais donc au prix d'un flush TLB à chaque changement de contexte.
[^] # Re: Question bête…
Posté par Sphax . Évalué à 1.
A noter que tant que j'ai pas de trafic sur apache, postgresql n'a aucun problème.
J'ai essayé de changer les paramètres de ulimit (comme le max locked memory) en mettant les paramètres de mon ancien serveur qui fonctionne, ça n'a rien changé.
A noter aussi que là j'utilise apache avec le MPM prefork, et qu'avant hier quand j'utilisais le MPM event avec PHP en CGI je n'avais pas ces problèmes.
[^] # NUMA? kernel leak? userland leak? mm bug?
Posté par Krunch (site web personnel) . Évalué à 1.
pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.
# Suite
Posté par Sphax . Évalué à 1.
[^] # Re: Suite
Posté par NeoX . Évalué à 2.
ton prefork ouvre des processes en attente de connexion potentielle.
=> apache va ouvrir
5 prefork (il me semble par defaut) et va tacher d'en avoir toujours 5 d'avances.
si tu as 1000 clients, il va donc tacher d'ouvrir 1005 process.
=> avec un keepalive à 15sec, chaque client qui se connecte ne serait-ce qu'une fois, laisse le process en attente pour 15sec meme s'il ne se passe rien
il faut surtout essayer de voire ce qui se passe quand ca plante, par exemple ce que dit un
ps fax | grep apache quand ca "plante"
[^] # Re: Suite
Posté par netsurfeur . Évalué à 2.
Par défaut, il est à 150. C'est très bien pour des process apache légers. Par contre, avec des process lourds c'est excessif.
Dans ton cas, avec 512 Mo/process (limite PHP), tu risques d'avoir besoin de 150*0.5Go = 75 Go de RAM.
Le fait que la réduction du KeepAliveTimeout résolve le problème semble confirmer l'hypothèse : avec un KeepAliveTimeout plus faible, il y a moins de process Apache.
Par ailleurs, tu as intérêt à avoir un MaxRequestsPerChild non nul pour que les process Apache puissent rendre périodiquement la mémoire allouée.
[^] # Re: Suite
Posté par Sphax . Évalué à 1.
De plus le 512Mo par process PHP est une limite, pas une valeur toujours atteinte; on a aucun script qui va consommer jusqu'à 512Mo de mémoire.
Concernant le MaxRequestsPerChild on est à 10000.
[^] # Re: Suite
Posté par netsurfeur . Évalué à 1.
Pourtant, d'après tes dires, la seule modification a été le passage d'Apache MPM event à MPM prefork. Autrement dit, d'un Apache léger un utilisation mémoire à un Apache "lourd".
Avec 32 Go de RAM - les 6 Go de Postgres, pas besoin d'atteindre les 512 Mo par process Apache pour exploser la RAM si 150 process sont démarrés.
[^] # Re: Suite
Posté par Sphax . Évalué à 1.
De plus, on atteint sans problème 3000 process Apache avec cette configuration, la plupart consomment quasiment rien en mémoire (et notre script php le plus appelé travaille sur peu de données, de l'ordre de quelques Ko).
Mais grâce à l'explication de neologix plus bas, j'ai cherché les effets sur Apache du passage de la variable vm.overcommit_memory à 2. Et d'après un post sur serverfault.com, ça ne fait pas bon ménage.
Bon j'ai pas pu tester en revenant sur un KeepAliveTimeout à 15, mais rien que là en observant le fichier /proc/meminfo j'ai vu que la valeur de Committed_AS a tendance à dépasser CommitLimit.
Si j'ai bien compris ce que j'ai lu, en passant overcommit_memory à 2 ça serait impossible, ce qui expliquerait les problèmes d'allocation mémoire commun à Postgresql, Apache, PHP et exim. Ça me parait le plus probable.
En tout cas cette histoire m'apprendra à faire de la pré-optimisation...
# attention à l'overcommitting
Posté par neologix . Évalué à 2.
Que renvoie un "cat /proc/meminfo" (particulièrement la ligne committed_AS) ?
[^] # Re: attention à l'overcommitting
Posté par Sphax . Évalué à 1.
vm.overcommit_memory = 2
vm.overcommit_ratio = 100
Ce n'est pas les paramètres par défaut, j'avais appliqué ces changements en me basant sur les recommandations du livre "Postgresql 9.0 High Performance".
/proc/meminfo:
Committed_AS: 18687308 kB
Ça fait 17Go, mais que représente cette ligne ?
[^] # Re: attention à l'overcommitting
Posté par neologix . Évalué à 2.
vm.overcommit_ratio = 100
Ce n'est pas les paramètres par défaut, j'avais appliqué ces changements en me basant sur les recommandations du livre "Postgresql 9.0 High Performance".
Cela désactive l'overcommiting, cela signifie que le noyau n'allouera pas plus de SWAP + 100% RAM = SWAP + RAM. Sans cela, malloc peut renvoyer une adresse valide (i.e. pas NULL), mais l'OOM-killer se mettra en branle au moment où elle touchera les pages.
/proc/meminfo:
Committed_AS: 18687308 kB
Ça fait 17Go, mais que représente cette ligne ?
La mémoire réellement allouée. Le problème c'est que la valeur reportée par free (même en prenant en compte buffer/cache) est à peu près aussi fiable que madame Soleil : par exemple, sur certains noyaux, avec un FS ext3 monté avec data=ordered, si tu supprimes un fichier alors qu'il est ouvert, le taille reportée du page cache diminue, mais pas la mémoire free.
Un autre problème, c'est que tant que la page n'a pas été touchée par l'application, elle ne sera pas reportée comme utilisée.
Committed_AS est la quantité de mémoire qui a été réellement allouée par le noyau.
Il serait bien de faire un "watch cat /proc/meminfo" pendant que tu es en charge...
[^] # Re: attention à l'overcommitting
Posté par Sphax . Évalué à 1.
J'ai bien envie de tester en monitorant meminfo pour en avoir le coeur net mais comme c'est une machine de prod et qu'on a contourné le problème je pense pas que mon chef sera d'accord.
En tout cas merci pour les explications.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.