web-dev-qa-db-fra.com

Utilisation inhabituellement élevée du cache de dentisterie

Problème

Une machine CentOS avec noyau 2.6.32 et 128 Go physique RAM a rencontré des problèmes il y a quelques jours. L'administrateur système responsable me dit que l'application PHP-FPM ne répondait pas aux demandes en temps opportun manière due à l'échange, et ayant vu dans free qu'il ne restait presque plus de mémoire, il a choisi de redémarrer la machine.

Je sais que la mémoire libre peut être un concept déroutant sous Linux et un redémarrage n'était peut-être pas la bonne chose à faire. Cependant, l'administrateur mentionné accuse l'application PHP (dont je suis responsable) et refuse d'enquêter plus avant.

Ce que j'ai pu découvrir par moi-même, c'est ceci:

  • Avant le redémarrage, la mémoire libre (y compris les tampons et le cache) n'était que de quelques centaines de Mo.
  • Avant le redémarrage, /proc/meminfo A signalé une utilisation de la mémoire Slab d'environ 90 Go (oui, Go).
  • Après le redémarrage, la mémoire libre était de 119 Go, descendant à environ 100 Go en une heure, alors que les travailleurs PHP-FPM (environ 600 d'entre eux) revenaient à la vie, chacun montrant entre 30 et 40 Mo dans le La colonne RES en haut (qui est ainsi depuis des mois et est parfaitement raisonnable compte tenu de la nature de l'application PHP). Il n'y a rien d'autre dans la liste des processus qui consomme une quantité inhabituelle ou notable de RAM.
  • Après le redémarrage, la mémoire de la dalle était d'environ 300 Mo

Depuis, il surveille le système, et notamment la mémoire de la dalle augmente en ligne droite avec un débit d'environ 5 Go par jour. La mémoire disponible telle que rapportée par free et /proc/meminfo Diminue au même rythme. La dalle est actuellement de 46 Go. Selon slabtop, la plus grande partie est utilisée pour les entrées dentry:

Mémoire libre:

free -m
             total       used       free     shared    buffers     cached
Mem:        129048      76435      52612          0        144       7675
-/+ buffers/cache:      68615      60432
Swap:         8191          0       8191

Meminfo:

cat /proc/meminfo
MemTotal:       132145324 kB
MemFree:        53620068 kB
Buffers:          147760 kB
Cached:          8239072 kB
SwapCached:            0 kB
Active:         20300940 kB
Inactive:        6512716 kB
Active(anon):   18408460 kB
Inactive(anon):    24736 kB
Active(file):    1892480 kB
Inactive(file):  6487980 kB
Unevictable:        8608 kB
Mlocked:            8608 kB
SwapTotal:       8388600 kB
SwapFree:        8388600 kB
Dirty:             11416 kB
Writeback:             0 kB
AnonPages:      18436224 kB
Mapped:            94536 kB
Shmem:              6364 kB
Slab:           46240380 kB
SReclaimable:   44561644 kB
SUnreclaim:      1678736 kB
KernelStack:        9336 kB
PageTables:       457516 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    72364108 kB
Committed_AS:   22305444 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      480164 kB
VmallocChunk:   34290830848 kB
HardwareCorrupted:     0 kB
AnonHugePages:  12216320 kB
HugePages_Total:    2048
HugePages_Free:     2048
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:        5604 kB
DirectMap2M:     2078720 kB
DirectMap1G:    132120576 kB

Dalle:

slabtop --once
Active / Total Objects (% used)    : 225920064 / 226193412 (99.9%)
 Active / Total Slabs (% used)      : 11556364 / 11556415 (100.0%)
 Active / Total Caches (% used)     : 110 / 194 (56.7%)
 Active / Total Size (% used)       : 43278793.73K / 43315465.42K (99.9%)
 Minimum / Average / Maximum Object : 0.02K / 0.19K / 4096.00K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
221416340 221416039   3%    0.19K 11070817       20  44283268K dentry                 
1123443 1122739  99%    0.41K 124827        9    499308K Fuse_request           
1122320 1122180  99%    0.75K 224464        5    897856K Fuse_inode             
761539 754272  99%    0.20K  40081       19    160324K vm_area_struct         
437858 223259  50%    0.10K  11834       37     47336K buffer_head            
353353 347519  98%    0.05K   4589       77     18356K anon_vma_chain         
325090 324190  99%    0.06K   5510       59     22040K size-64                
146272 145422  99%    0.03K   1306      112      5224K size-32                
137625 137614  99%    1.02K  45875        3    183500K nfs_inode_cache        
128800 118407  91%    0.04K   1400       92      5600K anon_vma               
 59101  46853  79%    0.55K   8443        7     33772K radix_tree_node        
 52620  52009  98%    0.12K   1754       30      7016K size-128               
 19359  19253  99%    0.14K    717       27      2868K sysfs_dir_cache        
 10240   7746  75%    0.19K    512       20      2048K filp  

Pression du cache VFS:

cat /proc/sys/vm/vfs_cache_pressure
125

Swappiness:

cat /proc/sys/vm/swappiness
0

Je sais que la mémoire inutilisée est de la mémoire gaspillée, donc cela ne devrait pas nécessairement être une mauvaise chose (surtout étant donné que 44 Go sont affichés comme SReclaimable). Cependant, apparemment, la machine a néanmoins rencontré des problèmes, et je crains que la même chose ne se reproduise dans quelques jours lorsque Slab dépassera 90 Go.

Des questions

J'ai ces questions:

  • Ai-je raison de penser que la mémoire de la dalle est toujours de la RAM physique et que le nombre est déjà soustrait de la valeur MemFree?
  • Un nombre aussi élevé d'entrées dentaires est-il normal? L'application PHP a accès à environ 1,5 million de fichiers, mais la plupart d'entre eux sont des archives et ne sont pas du tout accessibles pour le trafic Web normal.
  • Quelle pourrait être l'explication du fait que le nombre d'inodes mis en cache est bien inférieur au nombre de dentiers mis en cache, ne devraient-ils pas être liés d'une manière ou d'une autre?
  • Si le système rencontre des problèmes de mémoire, le noyau ne doit-il pas libérer automatiquement certaines denteries? Quelle pourrait être la raison pour laquelle cela ne se produit pas?
  • Existe-t-il un moyen de "regarder" dans le cache dentry pour voir ce qu'est toute cette mémoire (c'est-à-dire quels sont les chemins qui sont mis en cache)? Peut-être que cela pointe vers une sorte de fuite de mémoire, de boucle de lien symbolique, ou bien vers quelque chose que l'application PHP fait mal).
  • Le code d'application PHP ainsi que tous les fichiers de ressources sont montés via le système de fichiers réseau GlusterFS, cela pourrait-il avoir quelque chose à voir avec cela?

Veuillez garder à l'esprit que je ne peux pas enquêter en tant que root, uniquement en tant qu'utilisateur régulier, et que l'administrateur refuse d'aider. Il n'exécutera même pas le test echo 2 > /proc/sys/vm/drop_caches Typique pour voir si la mémoire Slab est effectivement récupérable.

Tout aperçu de ce qui pourrait se passer et de la façon dont je peux enquêter plus avant serait grandement apprécié.

Mises à jour

Quelques informations de diagnostic supplémentaires:

Montures:

cat /proc/self/mounts
rootfs / rootfs rw 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,relatime 0 0
devtmpfs /dev devtmpfs rw,relatime,size=66063000k,nr_inodes=16515750,mode=755 0 0
devpts /dev/pts devpts rw,relatime,gid=5,mode=620,ptmxmode=000 0 0
tmpfs /dev/shm tmpfs rw,relatime 0 0
/dev/mapper/sysvg-lv_root / ext4 rw,relatime,barrier=1,data=ordered 0 0
/proc/bus/usb /proc/bus/usb usbfs rw,relatime 0 0
/dev/sda1 /boot ext4 rw,relatime,barrier=1,data=ordered 0 0
tmpfs /phptmp tmpfs rw,noatime,size=1048576k,nr_inodes=15728640,mode=777 0 0
tmpfs /wsdltmp tmpfs rw,noatime,size=1048576k,nr_inodes=15728640,mode=777 0 0
none /proc/sys/fs/binfmt_misc binfmt_misc rw,relatime 0 0
cgroup /cgroup/cpuset cgroup rw,relatime,cpuset 0 0
cgroup /cgroup/cpu cgroup rw,relatime,cpu 0 0
cgroup /cgroup/cpuacct cgroup rw,relatime,cpuacct 0 0
cgroup /cgroup/memory cgroup rw,relatime,memory 0 0
cgroup /cgroup/devices cgroup rw,relatime,devices 0 0
cgroup /cgroup/freezer cgroup rw,relatime,freezer 0 0
cgroup /cgroup/net_cls cgroup rw,relatime,net_cls 0 0
cgroup /cgroup/blkio cgroup rw,relatime,blkio 0 0
/etc/glusterfs/glusterfs-www.vol /var/www Fuse.glusterfs rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072 0 0
/etc/glusterfs/glusterfs-upload.vol /var/upload Fuse.glusterfs rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072 0 0
sunrpc /var/lib/nfs/rpc_pipefs rpc_pipefs rw,relatime 0 0
172.17.39.78:/www /data/www nfs rw,relatime,vers=3,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,port=38467,timeo=600,retrans=2,sec=sys,mountaddr=172.17.39.78,mountvers=3,mountport=38465,mountproto=tcp,local_lock=none,addr=172.17.39.78 0 0

Informations sur le montage:

cat /proc/self/mountinfo
16 21 0:3 / /proc rw,relatime - proc proc rw
17 21 0:0 / /sys rw,relatime - sysfs sysfs rw
18 21 0:5 / /dev rw,relatime - devtmpfs devtmpfs rw,size=66063000k,nr_inodes=16515750,mode=755
19 18 0:11 / /dev/pts rw,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000
20 18 0:16 / /dev/shm rw,relatime - tmpfs tmpfs rw
21 1 253:1 / / rw,relatime - ext4 /dev/mapper/sysvg-lv_root rw,barrier=1,data=ordered
22 16 0:15 / /proc/bus/usb rw,relatime - usbfs /proc/bus/usb rw
23 21 8:1 / /boot rw,relatime - ext4 /dev/sda1 rw,barrier=1,data=ordered
24 21 0:17 / /phptmp rw,noatime - tmpfs tmpfs rw,size=1048576k,nr_inodes=15728640,mode=777
25 21 0:18 / /wsdltmp rw,noatime - tmpfs tmpfs rw,size=1048576k,nr_inodes=15728640,mode=777
26 16 0:19 / /proc/sys/fs/binfmt_misc rw,relatime - binfmt_misc none rw
27 21 0:20 / /cgroup/cpuset rw,relatime - cgroup cgroup rw,cpuset
28 21 0:21 / /cgroup/cpu rw,relatime - cgroup cgroup rw,cpu
29 21 0:22 / /cgroup/cpuacct rw,relatime - cgroup cgroup rw,cpuacct
30 21 0:23 / /cgroup/memory rw,relatime - cgroup cgroup rw,memory
31 21 0:24 / /cgroup/devices rw,relatime - cgroup cgroup rw,devices
32 21 0:25 / /cgroup/freezer rw,relatime - cgroup cgroup rw,freezer
33 21 0:26 / /cgroup/net_cls rw,relatime - cgroup cgroup rw,net_cls
34 21 0:27 / /cgroup/blkio rw,relatime - cgroup cgroup rw,blkio
35 21 0:28 / /var/www rw,relatime - Fuse.glusterfs /etc/glusterfs/glusterfs-www.vol rw,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072
36 21 0:29 / /var/upload rw,relatime - Fuse.glusterfs /etc/glusterfs/glusterfs-upload.vol rw,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072
37 21 0:30 / /var/lib/nfs/rpc_pipefs rw,relatime - rpc_pipefs sunrpc rw
39 21 0:31 / /data/www rw,relatime - nfs 172.17.39.78:/www rw,vers=3,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,port=38467,timeo=600,retrans=2,sec=sys,mountaddr=172.17.39.78,mountvers=3,mountport=38465,mountproto=tcp,local_lock=none,addr=172.17.39.78

Configuration de GlusterFS:

cat /etc/glusterfs/glusterfs-www.vol
volume remote1
  type protocol/client
  option transport-type tcp
  option remote-Host 172.17.39.71
   option ping-timeout 10
   option transport.socket.nodelay on # undocumented option for speed
    # http://gluster.org/pipermail/gluster-users/2009-September/003158.html
  option remote-subvolume /data/www
end-volume

volume remote2
  type protocol/client
  option transport-type tcp
  option remote-Host 172.17.39.72
   option ping-timeout 10
   option transport.socket.nodelay on # undocumented option for speed
        # http://gluster.org/pipermail/gluster-users/2009-September/003158.html
  option remote-subvolume /data/www
end-volume

volume remote3
  type protocol/client
  option transport-type tcp
  option remote-Host 172.17.39.73
   option ping-timeout 10
   option transport.socket.nodelay on # undocumented option for speed
        # http://gluster.org/pipermail/gluster-users/2009-September/003158.html
  option remote-subvolume /data/www
end-volume

volume remote4
  type protocol/client
  option transport-type tcp
  option remote-Host 172.17.39.74
   option ping-timeout 10
   option transport.socket.nodelay on # undocumented option for speed
        # http://gluster.org/pipermail/gluster-users/2009-September/003158.html
  option remote-subvolume /data/www
end-volume

volume replicate1
  type cluster/replicate
   option lookup-unhashed off    # off will reduce cpu usage, and network
   option local-volume-name 'hostname'
  subvolumes remote1 remote2
end-volume

volume replicate2
  type cluster/replicate
   option lookup-unhashed off    # off will reduce cpu usage, and network
   option local-volume-name 'hostname'
  subvolumes remote3 remote4
end-volume

volume distribute
  type cluster/distribute
  subvolumes replicate1 replicate2
end-volume

volume iocache
  type performance/io-cache
   option cache-size 8192MB        # default is 32MB
   subvolumes distribute
end-volume

volume writeback
  type performance/write-behind
  option cache-size 1024MB
  option window-size 1MB
  subvolumes iocache
end-volume

### Add io-threads for parallel requisitions
volume iothreads
  type performance/io-threads
  option thread-count 64 # default is 16
  subvolumes writeback
end-volume

volume ra
  type performance/read-ahead
  option page-size 2MB
  option page-count 16
  option force-atime-update no
  subvolumes iothreads
end-volume
34
Wolfgang Stengel

Ai-je raison de penser que la mémoire de la dalle est toujours de la RAM physique et que le nombre est déjà soustrait de la valeur MemFree?

Oui.

Un nombre aussi élevé d'entrées dentaires est-il normal? L'application PHP a accès à environ 1,5 million de fichiers, mais la plupart d'entre eux sont des archives et ne sont pas du tout accessibles pour le trafic Web normal.

Oui, si le système n'est pas sous pression mémoire. Il doit utiliser la mémoire pour quelque chose, et il est possible que dans votre mode d'utilisation particulier, c'est la meilleure façon d'utiliser cette mémoire.

Quelle pourrait être l'explication du fait que le nombre d'inodes mis en cache est bien inférieur au nombre de dentiers mis en cache, ne devraient-ils pas être liés d'une manière ou d'une autre?

Beaucoup d'opérations d'annuaire seraient l'explication la plus probable.

Si le système rencontre des problèmes de mémoire, le noyau ne doit-il pas libérer automatiquement certaines denteries? Quelle pourrait être la raison pour laquelle cela ne se produit pas?

Il le devrait, et je ne vois aucune raison pour laquelle il ne le ferait pas. Je ne suis pas convaincu que c'est ce qui a vraiment mal tourné. Je suggère fortement de mettre à jour votre noyau ou d'augmenter encore vfs_cache_pressure.

Existe-t-il un moyen de "regarder" dans le cache dentry pour voir ce qu'est toute cette mémoire (c'est-à-dire quels sont les chemins qui sont mis en cache)? Peut-être que cela pointe vers une sorte de fuite de mémoire, de boucle de lien symbolique, ou bien vers quelque chose que l'application PHP fait mal).

Je n'y crois pas. Je rechercherais tous les répertoires avec un nombre absurdement élevé d'entrées ou des structures de répertoires très profondes qui sont recherchées ou parcourues.

Le code d'application PHP ainsi que tous les fichiers de ressources sont montés via le système de fichiers réseau GlusterFS, cela pourrait-il avoir quelque chose à voir avec cela?

Certainement, cela pourrait être un problème de système de fichiers. Un bug du système de fichiers empêchant la libération des dentiers, par exemple, est une possibilité.

14
David Schwartz

Solution confirmée

À tous ceux qui pourraient rencontrer le même problème. Les gars du centre de données l'ont finalement compris aujourd'hui. Le coupable était une bibliothèque NSS (Network Security Services) fournie avec Libcurl. Une mise à niveau vers la dernière version a résolu le problème.

Un rapport de bogue qui décrit les détails est ici:

https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=1044666

Apparemment, afin de déterminer si un chemin est local ou sur un lecteur réseau, NSS recherchait un fichier inexistant et mesurait le temps nécessaire au système de fichiers pour faire rapport! Si vous avez un nombre suffisant de demandes Curl et suffisamment de mémoire, ces demandes sont toutes mises en cache et empilées.

20
Wolfgang Stengel

J'ai rencontré ce problème exact, et même si Wolfgang a raison sur la cause, il manque des détails importants.

  • Ce problème affecte les demandes SSL effectuées avec curl ou libcurl, ou tout autre logiciel qui utilise mozilla NSS pour une connexion sécurisée. Les demandes non sécurisées ne déclenchent pas le problème.

  • Le problème ne nécessite pas de requêtes curl simultanées. L'accumulation de dentisterie se produira tant que les appels de boucles seront suffisamment fréquents pour dépasser les efforts du système d'exploitation pour récupérer de la RAM.

  • la nouvelle version de NSS, 3.16.0, inclut un correctif pour cela. cependant, vous n'obtenez pas le correctif gratuitement en mettant à niveau NSS, et vous n'avez pas à mettre à niveau tout NSS. vous n'avez qu'à mettre à niveau nss-softokn (qui a une dépendance requise sur nss-utils) au minimum. et pour en bénéficier, vous devez définir la variable d'environnement NSS_SDB_USE_CACHE pour le processus qui utilise libcurl. la présence de cette variable d'environnement permet d'éviter les vérifications de fichiers inexistantes coûteuses.

FWIW, j'ai écrit un entrée de blog avec un peu plus de contexte/détails, au cas où quelqu'un en aurait besoin.

15
J. Paulding

Voir https://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.7/2.6.7-mm1/broken-out/vfs-shrinkage-tuning.patch

Il y a des chiffres montrant que vous pouvez vous attendre à une récupération de mémoire dentinaire notable lorsque vfs_cache_pressure est défini sur une valeur supérieure à 100. Ainsi, 125 peut être trop faible pour que cela se produise dans votre cas.

4
poige

Pas vraiment une explication à votre réponse, mais en tant qu'utilisateur de ce système, ces informations que vous avez fournies:

cat /proc/meminfo
MemTotal:       132145324 kB
...
SReclaimable:   44561644 kB
SUnreclaim:      1678736 kB

Il suffit de me dire que ce n'est pas pas votre problème et que c'est la responsabilité du sysadmin de fournir une explication adéquate.

Je ne veux pas paraître grossier ici mais;

  • Vous manquez d'informations spécifiques sur le rôle de cet hôte.
  • La façon dont l'hôte est censé hiérarchiser les ressources est hors de votre portée.
  • Vous n'êtes pas familier ou avez participé à la conception et au déploiement du stockage sur cet hôte.
  • Vous ne pouvez pas offrir certaines sorties système car vous n'êtes pas root.

Il est de votre responsabilité sysadmins de justifier ou de résoudre l'anomalie d'allocation de dalle. Soit vous ne nous avez pas donné une image complète de toute la saga qui vous a amené à cela (ce qui ne m'intéresse pas franchement), soit votre administrateur système se comporte de manière irresponsable et/ou incompétente dans la manière dont il envisage de gérer ce problème.

N'hésitez pas à lui dire qu'un inconnu au hasard sur Internet pense qu'il ne prend pas ses responsabilités au sérieux.

3
Matthew Ife