Problema
Uma máquina CentOS com kernel 2.6.32 e 128 GB de RAM física 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 free
que quase não havia mais memória, ele optou por reiniciar 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 se fazer. No entanto, o administrador mencionado culpa o aplicativo PHP (pelo qual sou responsável) e se recusa a investigar mais.
O que eu pude descobrir sozinho é o seguinte:
- Antes do reinício, a memória livre (incluindo buffers e cache) era de apenas algumas centenas de MB.
- Antes do reinício,
/proc/meminfo
relatava um uso de memória Slab de cerca de 90 GB (sim, GB). - Após o reinício, a memória livre era de 119 GB, diminuindo para cerca de 100 GB em uma hora, quando os funcionários do PHP-FPM (cerca de 600 deles) estavam voltando à vida, cada um mostrando entre 30 e 40 MB no Coluna RES no topo (que tem sido assim há meses e é perfeitamente razoável, dada a natureza do aplicativo PHP). Não há mais nada na lista de processos que consome uma quantidade incomum ou digna de nota de RAM.
- Após o reinício, a memória Slab estava em torno de 300 MB
Se estiver monitorando o sistema desde então, e principalmente a memória Slab está aumentando em uma linha reta com uma taxa de cerca de 5 GB por dia. A memória livre é relatada free
e /proc/meminfo
diminui na mesma taxa. A laje está atualmente em 46 GB. De acordo com a slabtop
maioria, é usado para dentry
entradas:
Memoria 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 no cache do VFS:
cat /proc/sys/vm/vfs_cache_pressure
125
Swappiness:
cat /proc/sys/vm/swappiness
0
Eu sei que a memória não utilizada é memória desperdiçada, portanto isso não deve necessariamente ser uma coisa ruim (especialmente considerando que 44 GB são mostrados como SReclaimable). No entanto, aparentemente a máquina enfrentou problemas, e receio que o mesmo acontecerá novamente em alguns dias quando a Slab ultrapassar os 90 GB.
Questões
Eu tenho estas perguntas:
- Estou correto ao pensar que a memória Slab é sempre RAM física e o número já está subtraído do valor MemFree?
- Um número tão alto de entradas de dentista é normal? O aplicativo PHP tem acesso a arquivos de cerca de 1,5 M, no entanto, a maioria deles é arquivada e não está sendo acessada para tráfego regular na Web.
- O que poderia ser uma explicação para o fato de o número de inodes em cache ser muito menor que o número de dentries em cache, eles não deveriam estar relacionados de alguma forma?
- Se o sistema tiver problemas de memória, o kernel não deve liberar alguns dos dentries automaticamente? O que poderia ser uma razão para isso não acontecer?
- Existe alguma maneira de "examinar" 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 indique algum tipo de vazamento de memória, loop de ligação simbólica ou mesmo algo que o aplicativo PHP esteja fazendo de errado.
- O código do aplicativo PHP, bem como todos os arquivos de ativos, são montados através do sistema de arquivos de rede GlusterFS, isso poderia ter algo a ver com isso?
Lembre-se de que não posso investigar como root, apenas como um usuário comum, e que o administrador se recusa a ajudar. Ele nem fará o echo 2 > /proc/sys/vm/drop_caches
teste típico para ver se a memória do Slab é realmente recuperável.
Qualquer ideia sobre o que poderia estar acontecendo e como eu posso investigar mais seria muito apreciada.
Atualizações
Algumas informações adicionais de diagnóstico:
Suportes:
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
Informações da montagem:
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
cat /proc/self/mounts
e (talvez bastante longa)cat /proc/self/mountinfo
.cat /etc/nfsmount.conf
. Você também possui algum diretório que contenha muitos arquivos em seu diretório imediato?Respostas:
Sim.
Sim, se o sistema não estiver sob pressão de memória. Ele precisa usar a memória para alguma coisa e é possível que, em seu padrão de uso específico, essa seja a melhor maneira de usar essa memória.
Muitas operações de diretório seriam a explicação mais provável.
Deveria, e não consigo pensar em nenhum motivo que não faria. Não estou convencido de que foi isso que realmente deu errado. Eu sugiro atualizar o seu kernel ou aumentar ainda mais o vfs_cache_pressure.
Eu não acredito que exista. Eu procuraria por qualquer diretório com um número absurdamente grande de entradas ou estruturas de diretório muito profundas que sejam pesquisadas ou percorridas.
Definitivamente, pode ser um problema no sistema de arquivos. Um bug no sistema de arquivos que faz com que os dentries não sejam liberados, por exemplo, é uma possibilidade.
fonte
Solução confirmada
Para quem pode encontrar o mesmo problema. Os caras do data center finalmente descobriram hoje. O culpado era uma biblioteca NSS (Network Security Services) empacotada com Libcurl. Uma atualização para a versão mais recente resolveu o problema.
Um relatório de bug que descreve os detalhes está aqui:
https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=1044666
Aparentemente, para determinar se algum caminho é local ou em uma unidade de rede, o NSS procurava um arquivo inexistente e media o tempo necessário para o sistema de arquivos relatar! Se você tiver um número grande o suficiente de solicitações de Curl e memória suficiente, essas solicitações serão todas armazenadas em cache e empilhadas.
fonte
Encontrei exatamente esse problema e, embora Wolfgang esteja correto sobre a causa, faltam alguns detalhes importantes.
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á desde que as chamadas de curvatura sejam frequentes o suficiente para superar os esforços do sistema operacional para recuperar a RAM.
a versão mais recente 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 todo o 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, é necessário configurar a variável de ambiente NSS_SDB_USE_CACHE para o processo que está usando a 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 de experiência / detalhes, caso alguém precise.
fonte
nss-softoken
RPM E definir oNSS_SDB_USE_CACHE=YES
env var para que as chamadas https curl https parem de inundar seu cache de dentry.Consulte 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
Existem números mostrando que você pode esperar uma recuperação notável da memória do dentry quando o vfs_cache_pressure estiver definido como um valor superior a 100. Portanto, 125 pode ser muito baixo para que isso aconteça no seu caso.
fonte
vfs_cache_pressure
acima100
só faz sentido se você não tiver RAM suficiente para sua carga de trabalho. Nesse caso, ter um valor acima de 100 (por exemplo, 10000) liberará um pouco de RAM. Isso resultará em pior IO geral, no entanto.Não é realmente uma explicação para sua resposta, mas como usuário deste sistema, essas informações foram fornecidas:
É o suficiente para me dizer que este não é o seu problema e é responsabilidade do administrador do sistema fornecer uma explicação adequada.
Eu não quero parecer rude aqui, mas;
É de sua responsabilidade os administradores de sistemas do sistema justificar ou resolver a anomalia de alocação de laje. Ou você não nos deu uma imagem completa de toda a saga que o levou a isso (que sinceramente não estou interessado) ou o administrador do sistema está se comportando de forma irresponsável e / ou incompetente da maneira que ele considera lidar com esse problema.
Sinta-se livre para dizer a ele que um estranho aleatório na internet pensa que ele não está levando suas responsabilidades a sério.
fonte