Uso de caché de dentry inusualmente alto

34

Problema

Una máquina CentOS con kernel 2.6.32 y 128 GB de RAM física tuvo problemas hace unos días. El administrador del sistema responsable me dice que la aplicación PHP-FPM ya no respondía a las solicitudes de manera oportuna debido al intercambio, y al haber visto freeque casi no quedaba memoria, decidió reiniciar la máquina.

Sé que la memoria libre puede ser un concepto confuso en Linux y un reinicio tal vez fue algo incorrecto. Sin embargo, el administrador mencionado culpa a la aplicación PHP (de la que soy responsable) y se niega a investigar más a fondo.

Lo que podría descubrir por mi cuenta es esto:

  • Antes del reinicio, la memoria libre (incluidos los búferes y la memoria caché) era de solo unos cientos de MB.
  • Antes del reinicio, /proc/meminfoinformó un uso de memoria Slab de alrededor de 90 GB (sí, GB).
  • Después del reinicio, la memoria libre era de 119 GB, bajando a alrededor de 100 GB en una hora, a medida que los trabajadores de PHP-FPM (aproximadamente 600 de ellos) volvían a la vida, cada uno de ellos mostrando entre 30 y 40 MB en el Columna RES en la parte superior (que ha sido así durante meses y es perfectamente razonable dada la naturaleza de la aplicación PHP). No hay nada más en la lista de procesos que consuma una cantidad inusual o notable de RAM.
  • Después del reinicio, la memoria de losa era de aproximadamente 300 MB

Si ha estado monitoreando el sistema desde entonces, y más notablemente, la memoria Slab está aumentando en línea recta con una tasa de aproximadamente 5 GB por día. Memoria libre según lo informado por freey /proc/meminfodisminuye a la misma velocidad. Losa está actualmente en 46 GB. Según la slabtopmayor parte se utiliza para dentryentradas:

Memoria 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

Losa:

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  

Presión de caché VFS:

cat /proc/sys/vm/vfs_cache_pressure
125

Swappiness:

cat /proc/sys/vm/swappiness
0

Sé que la memoria no utilizada es memoria desperdiciada, por lo que esto no debería ser necesariamente algo malo (especialmente dado que 44 GB se muestran como SReclaimable). Sin embargo, aparentemente la máquina experimentó problemas, y me temo que lo mismo volverá a ocurrir en unos días cuando Slab supere los 90 GB.

Preguntas

Tengo estas preguntas:

  • ¿Estoy en lo cierto al pensar que la memoria Slab es siempre RAM física y que el número ya se resta del valor MemFree?
  • ¿Es normal un número tan alto de entradas de dentry? La aplicación PHP tiene acceso a alrededor de 1.5 M de archivos, sin embargo, la mayoría de ellos son archivos y no se accede a ellos para el tráfico web regular.
  • ¿Cuál podría ser una explicación del hecho de que el número de inodos almacenados en caché es mucho menor que el número de dentries almacenados en caché, no deberían estar relacionados de alguna manera?
  • Si el sistema tiene problemas de memoria, ¿el núcleo no debería liberar algunas de las dentries automáticamente? ¿Cuál podría ser una razón por la que esto no sucede?
  • ¿Hay alguna forma de "mirar" el caché de dentry para ver qué es toda esta memoria (es decir, cuáles son las rutas que se almacenan en caché)? Quizás esto apunta a algún tipo de pérdida de memoria, bucle de enlace simbólico o, de hecho, a algo que la aplicación PHP está haciendo mal.
  • El código de la aplicación PHP, así como todos los archivos de activos, se montan a través del sistema de archivos de red GlusterFS, ¿podría eso tener algo que ver con eso?

Tenga en cuenta que no puedo investigar como root, solo como un usuario normal, y que el administrador se niega a ayudar. Ni siquiera ejecutará la echo 2 > /proc/sys/vm/drop_cachesprueba típica para ver si la memoria Slab es realmente recuperable.

Cualquier idea sobre lo que podría estar sucediendo y cómo puedo investigar más sería muy apreciada.

Actualizaciones

Alguna información de diagnóstico adicional:

Monturas:

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

Información de montaje:

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

Configuración 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
Wolfgang Stengel
fuente
Proporcione el resultado de cat /proc/self/mountsy (tal vez bastante largo) cat /proc/self/mountinfo.
Matthew Ife
@MIfe He actualizado la pregunta, se anexan ambas salidas.
Wolfgang Stengel
Mi sensación aquí es que probablemente tenga que ver con el almacenamiento en caché dentry de NFS. Fuera de interés puedes correr cat /etc/nfsmount.conf. ¿También tiene algún directorio que contenga muchos archivos en su directorio inmediato?
Matthew Ife
1
Bueno, desde vfs_cache_pressure> 100, el núcleo debería preferir reclamar la memoria caché dentrie. Esto puede ser fácilmente un error, 2.6.32 es un kernel bastante antiguo, incluso con parches de redport de Backat. Por cierto, ¿cuál es la versión exacta del kernel?
poige
2
(Su administrador de sistemas suena terrible . Nos da un mal nombre)
ewwhite

Respuestas:

14

¿Estoy en lo cierto al pensar que la memoria Slab es siempre RAM física y que el número ya se resta del valor MemFree?

Sí.

¿Es normal un número tan alto de entradas de dentry? La aplicación PHP tiene acceso a alrededor de 1.5 M de archivos, sin embargo, la mayoría de ellos son archivos y no se accede a ellos para el tráfico web regular.

Sí, si el sistema no está bajo presión de memoria. Tiene que usar la memoria para algo, y es posible que en su patrón particular de uso, esta sea la mejor manera de usar esa memoria.

¿Cuál podría ser una explicación del hecho de que el número de inodos almacenados en caché es mucho menor que el número de dentries almacenados en caché, no deberían estar relacionados de alguna manera?

Muchas operaciones de directorio serían la explicación más probable.

Si el sistema tiene problemas de memoria, ¿el núcleo no debería liberar algunas de las dentries automáticamente? ¿Cuál podría ser una razón por la que esto no sucede?

Debería, y no puedo pensar en ninguna razón por la que no lo haría. No estoy convencido de que esto sea lo que realmente salió mal. Sugeriría encarecidamente actualizar su kernel o aumentar vfs_cache_pressure aún más.

¿Hay alguna forma de "mirar" el caché de dentry para ver qué es toda esta memoria (es decir, cuáles son las rutas que se almacenan en caché)? Quizás esto apunta a algún tipo de pérdida de memoria, bucle de enlace simbólico o, de hecho, a algo que la aplicación PHP está haciendo mal.

No creo que haya. Buscaría cualquier directorio con un número absurdamente grande de entradas o estructuras de directorios muy profundas que se buscan o recorren.

El código de la aplicación PHP, así como todos los archivos de activos, se montan a través del sistema de archivos de red GlusterFS, ¿podría eso tener algo que ver con eso?

Definitivamente podría ser un problema del sistema de archivos. Es posible que se produzca un error en el sistema de archivos que hace que no se publiquen dentries.

David Schwartz
fuente
Gracias por responder mis preguntas individualmente. La presión de caché finalmente se incrementó aún más y el aumento de caché de dentry se detuvo.
Wolfgang Stengel
Todavía no pude localizar el programa responsable. Si descubro más, informaré a cualquier otra persona que tenga este problema.
Wolfgang Stengel el
1
¡Gracias! El gran directorio (archivos de 0.25 mil) fue totalmente la causa del problema en mi caso, cada vez que algo interactuaba con él, 2GB de RAM desaparecerían en el caché.
Algunos Linux Nerd
20

Solución confirmada

Para cualquiera que pueda encontrarse con el mismo problema. Los chicos del centro de datos finalmente lo descubrieron hoy. El culpable era una biblioteca NSS (Network Security Services) incluida con Libcurl. Una actualización a la versión más nueva resolvió el problema.

Un informe de error que describe los detalles está aquí:

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

Aparentemente, para determinar si alguna ruta es local o en una unidad de red, NSS estaba buscando un archivo inexistente y midiendo el tiempo que le tomó al sistema de archivos informar. Si tiene un número suficientemente grande de solicitudes Curl y suficiente memoria, todas estas solicitudes se almacenan en caché y se apilan.

Wolfgang Stengel
fuente
15

Me encontré con este problema exacto, y aunque Wolfgang tiene razón sobre la causa, faltan algunos detalles importantes.

  • Este problema afecta a las solicitudes SSL realizadas con curl o libcurl, o cualquier otro software que utilice Mozilla NSS para una conexión segura. Las solicitudes no seguras no desencadenan el problema.

  • El problema no requiere solicitudes de curl concurrentes. La acumulación de negación ocurrirá mientras las llamadas curl sean lo suficientemente frecuentes como para superar los esfuerzos del sistema operativo para recuperar RAM.

  • la versión más nueva de NSS, 3.16.0, incluye una solución para esto. sin embargo, no obtiene la solución de forma gratuita al actualizar NSS, y no tiene que actualizar todo NSS. solo tiene que actualizar nss-softokn (que tiene una dependencia requerida en nss-utils) como mínimo. y para obtener el beneficio, debe establecer la variable de entorno NSS_SDB_USE_CACHE para el proceso que usa libcurl. La presencia de esa variable de entorno es lo que permite omitir las costosas comprobaciones de archivos inexistentes.

FWIW, escribí una entrada de blog con un poco más de antecedentes / detalles, en caso de que alguien lo necesite.

J. Paulding
fuente
Gracias por una buena publicación de blog, pero me gustaría mencionar que nss-softokn todavía no se ha actualizado a la versión 3.16 en CentOS / RHEL. Probablemente se reparará en la versión 6.6.
Strahinja Kustudic
1
Gracias por la nota Quizás Amazon se adelantó a este (¿tal vez incluso a petición nuestra?) Por sus repositorios administrados. En versiones anteriores (3.14-3.15), aún obtiene la mitad del beneficio al configurar las variables de entorno apropiadas. Si tiene los conocimientos, es posible que pueda compilar v3.16 directamente. De lo contrario, aumentar la presión de caché y tomar el golpe de CPU asociado podría ser su mejor apuesta para un rendimiento confiable.
J. Paulding
3
Esto se soluciona en Centos 6.6 con nss-softokn-3.14.3-17
Strahinja Kustudic el
1
Solo para que quede claro para las personas que buscan una solución rápida: debe actualizar el nss-softokenRPM y configurar la NSS_SDB_USE_CACHE=YESvariable de entorno para que las llamadas curvilíneas https dejen de inundar su caché de dentry.
Steve Kehlet
4

Ver 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

Hay números que muestran que puede esperar una recuperación de memoria de dentry notable cuando vfs_cache_pressure se establece en una forma superior a 100. Entonces 125 puede ser demasiado bajo para que suceda en su caso.

poige
fuente
De todo lo que he leído, aumentar por vfs_cache_pressureencima 100solo tiene sentido si no tienes suficiente RAM para tu carga de trabajo. En ese caso, tener un valor muy superior a 100 (por ejemplo, 10000) liberará algo de RAM. Sin embargo, eso dará como resultado un peor IO en general.
Mikko Rantalainen
3

No es realmente una explicación a su respuesta, pero como usuario de este sistema, esta información que proporcionó:

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

Es suficiente para decirme que este no es su problema y es responsabilidad del administrador del sistema proporcionar una explicación adecuada.

No quiero sonar grosero aquí pero;

  • Carece de información específica sobre el papel de este host.
  • Cómo se supone que el host debe priorizar los recursos está fuera de su alcance.
  • No está familiarizado o participó en el diseño y la implementación del almacenamiento en este host.
  • No puede ofrecer ciertos resultados del sistema ya que no es root.

Es su responsabilidad de los administradores de sistemas justificar o resolver la anomalía de asignación de losas. O no nos ha dado una imagen completa de toda la saga que lo llevó a esto (que francamente no me interesa) o su administrador de sistemas se está comportando de manera irresponsable o incompetente en la forma en que considera manejar este problema.

Siéntase libre de decirle que algún extraño al azar en Internet cree que no se está tomando en serio sus responsabilidades.

Matthew Ife
fuente