Uso de cache dentário excepcionalmente alto

32

Problema

Uma máquina CentOS com RAM física de kernel 2.6.32 e 128 GB teve problemas alguns dias atrás. O administrador do sistema responsável me diz que o aplicativo PHP-FPM não estava mais respondendo às solicitações em tempo hábil devido à troca, e tendo visto em free que quase nenhuma memória foi deixada, ele optou por reinicializar a máquina.

Eu sei que a memória livre pode ser um conceito confuso no Linux, e uma reinicialização talvez tenha sido a coisa errada a fazer. No entanto, o administrador mencionado culpa o aplicativo PHP (do qual sou responsável) e se recusa a investigar mais.

O que eu consegui descobrir sozinho é o seguinte:

  • Antes da reinicialização, a memória livre (incluindo buffers e cache) era de apenas algumas centenas de MB.
  • Antes da reinicialização, /proc/meminfo relatou um uso de memória Slab de cerca de 90 GB (sim, GB).
  • Após a reinicialização, a memória livre ficou em 119 GB, caindo para cerca de 100 GB em uma hora, enquanto os funcionários do PHP-FPM (cerca de 600 deles) voltavam à vida, cada um mostrando entre 30 e 40 MB na coluna RES no topo (que tem sido assim há meses e é perfeitamente razoável, dada a natureza da aplicação PHP). Não há mais nada na lista de processos que consuma uma quantidade incomum ou notável de RAM.
  • Após a reinicialização, a memória Slab estava em torno de 300 MB

Se estiver monitorando o sistema desde então, e mais notavelmente a memória do Slab está aumentando em uma linha reta com uma taxa de cerca de 5 GB por dia. A memória livre, conforme relatada por free e /proc/meminfo , diminui na mesma proporção. A laje está atualmente em 46 GB. De acordo com slabtop , a maior parte é usada para dentry entradas:

Memória livre:

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

Slabtop:

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  

Pressão do cache do VFS:

cat /proc/sys/vm/vfs_cache_pressure
125

Swappiness:

cat /proc/sys/vm/swappiness
0

Eu sei que memória não utilizada é memória desperdiçada, então isso não deve necessariamente ser uma coisa ruim (especialmente considerando que 44 GB são mostrados como SReclamavel). No entanto, aparentemente, a máquina sofreu problemas, no entanto, e eu tenho medo que o mesmo aconteça novamente em alguns dias, quando o Slab ultrapassar 90 GB.

Perguntas

Eu tenho estas perguntas:

  • Estou correto ao pensar que a memória Slab é sempre RAM física, e o número já é subtraído do valor MemFree?
  • Um número tão alto de entradas dentárias é normal? O aplicativo PHP tem acesso a cerca de 1,5 milhões de arquivos, no entanto, a maioria deles são arquivos e não são acessados para tráfego regular na web.
  • O que poderia ser uma explicação para o fato de que o número de inodes em cache é muito menor do que o número de dentries em cache, caso eles não estejam relacionados de alguma forma?
  • Se o sistema entrar em problemas de memória, o kernel não deve liberar algumas dentaduras automaticamente? O que poderia ser uma razão para que isso não aconteça?
  • Existe alguma maneira de "investigar" o cache do dentry para ver o que é toda essa memória (ou seja, quais são os caminhos que estão sendo armazenados em cache)? Talvez isso aponte para algum tipo de vazamento de memória, loop symlink ou, de fato, para algo que a aplicação PHP está fazendo errado.
  • O código do aplicativo PHP, bem como todos os arquivos de ativos, são montados via sistema de arquivos de rede GlusterFS. Isso poderia ter algo a ver com isso?

Por favor, tenha em mente que eu não posso investigar como root, apenas como um usuário comum, e que o administrador se recusa a ajudar. Ele nem mesmo executará o teste típico echo 2 > /proc/sys/vm/drop_caches para ver se a memória Slab é realmente recuperável.

Qualquer ideia sobre o que poderia estar acontecendo e como eu poderia investigar mais seria muito apreciada.

Atualizações

Algumas informações adicionais de diagnóstico:

Montagens:

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

Montar informações:

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

Configuração do 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
    
por Wolfgang Stengel 14.12.2013 / 14:59

5 respostas

13

Am I correct in thinking that the Slab memory is always physical RAM, and the number is already subtracted from the MemFree value?

Sim.

Is such a high number of dentry entries normal? The PHP application has access to around 1.5 M files, however most of them are archives and not being accessed at all for regular web traffic.

Sim, se o sistema não estiver sob pressão de memória. Ele tem que usar a memória para algo, e é possível que em seu padrão particular de uso, essa seja a melhor maneira de usar essa memória.

What could be an explanation for the fact that the number of cached inodes is much lower than the number of cached dentries, should they not be related somehow?

Muitas operações de diretório seriam a explicação mais provável.

If the system runs into memory trouble, should the kernel not free some of the dentries automatically? What could be a reason that this does not happen?

Deveria, e não consigo pensar em nenhum motivo que não fosse. Eu não estou convencido de que isso é o que realmente deu errado. Eu sugiro strongmente atualizar seu kernel ou aumentar vfs_cache_pressure ainda mais.

Is there any way to "look into" the dentry cache to see what all this memory is (i.e. what are the paths that are being cached)? Perhaps this points to some kind of memory leak, symlink loop, or indeed to something the PHP application is doing wrong.

Eu não acredito que haja. Eu procuraria por quaisquer diretórios com um número absurdamente grande de entradas ou estruturas de diretório muito profundas que são pesquisadas ou percorridas.

The PHP application code as well as all asset files are mounted via GlusterFS network file system, could that have something to do with it?

Definitivamente, pode ser um problema no sistema de arquivos. Um bug no sistema de arquivos que faz com que dentries não sejam liberadas, por exemplo, é uma possibilidade.

    
por 15.12.2013 / 02:31
19

Solução confirmada

Para quem pode ter o mesmo problema. Os caras do data center finalmente descobriram isso hoje. O culpado foi uma biblioteca NSS (Network Security Services) incluída no Libcurl. Uma atualização para a versão mais recente resolveu o problema.

Um relatório de bug que descreve os detalhes está aqui:

link

Aparentemente, para determinar se algum caminho é local ou em uma unidade de rede, o NSS estava pesquisando um arquivo não existente e medindo o tempo que o sistema de arquivos levou para reportar! Se você tiver um grande número de solicitações de Curl e memória suficiente, essas solicitações serão armazenadas em cache e empilhadas.

    
por 24.01.2014 / 19:59
14

Eu me deparei com esse problema exato, e enquanto Wolfgang está correto sobre a causa, há alguns detalhes importantes faltando.

  • Esse problema afeta as solicitações SSL feitas com curl ou libcurl ou qualquer outro software que use o mozilla NSS para conexão segura. Solicitações não seguras não acionam o problema.

  • O problema não requer solicitações de curvatura simultâneas. O acúmulo de dentry ocorrerá enquanto as chamadas curl forem freqüentes o suficiente para superar os esforços do sistema operacional para recuperar RAM.

  • a nova versão do NSS, 3.16.0, inclui uma correção para isso. no entanto, você não obtém a correção gratuitamente ao atualizar o NSS e não precisa atualizar todos os NSS. você só precisa atualizar o nss-softokn (que tem uma dependência necessária do nss-utils) no mínimo. e para obter o benefício, você precisa definir a variável de ambiente NSS_SDB_USE_CACHE para o processo que está usando libcurl. a presença dessa variável de ambiente é o que permite que as verificações dispendiosas de arquivos inexistentes sejam ignoradas.

FWIW, escrevi uma entrada de blog com um pouco mais fundo / detalhes, caso alguém precise.

    
por 02.06.2014 / 21:30
3

Veja link

Existem números mostrando que você pode esperar alguma recuperação notável de memória dentária quando vfs_cache_pressure é definido de maneira superior a 100. Portanto, 125 pode ser muito baixo para que isso aconteça no seu caso.

    
por 14.12.2013 / 17:34
1

Não é realmente uma explicação para sua resposta, mas, como usuário deste sistema, essas informações foram fornecidas por você:

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

É o suficiente para me dizer que este não é o seu problema e é da responsabilidade do administrador de sistema fornecer uma explicação adequada.

Eu não quero soar rude aqui, mas;

  • Você não tem informações específicas sobre o papel desse host.
  • Como o host deve priorizar recursos está fora do seu escopo.
  • Você não está familiarizado ou teve alguma participação no design e na implantação do armazenamento nesse host.
  • Você não pode oferecer determinada saída do sistema, pois não é raiz.

É de sua responsabilidade sysadmins justificar ou resolver a anomalia de alocação de placas. Ou você não nos deu uma visão completa de toda a saga que o levou a isso (que francamente eu não estou interessado) ou seu administrador de sistema está se comportando de maneira irresponsável e / ou incompetente na maneira como ele considera lidar com esse problema. p>

Sinta-se à vontade para dizer a ele que algum estranho na internet acha que ele não está levando suas responsabilidades a sério.

    
por 14.12.2013 / 18:22