异常高的Dentry缓存使用率


34

问题

几天前,一台具有内核2.6.32和128 GB物理RAM的CentOS计算机就遇到了麻烦。负责的系统管理员告诉我,由于交换,PHP-FPM应用程序不再及时响应请求,并且由于发现free几乎没有内存,他选择重新启动计算机。

我知道空闲内存在Linux上可能是一个令人困惑的概念,重启可能是错误的事情。但是,上述管理员将责任归咎于PHP应用程序(由我负责),并且拒绝进一步调查。

我自己能发现的是:

  • 重新启动之前,可用内存(包括缓冲区和缓存)只有几百MB。
  • 重新启动之前,/proc/meminfo报告的Slab内存使用量约为90 GB(是,GB)。
  • 重新启动后,可用内存为119 GB,在一小时内下降到约100 GB,这是因为PHP-FPM工作人员(其中约600名)恢复了活力,每个工作人员在30至40 MB的内存中显示。 RES列在顶部(这种方式已经使用了几个月,并且考虑到PHP应用程序的性质,这是完全合理的)。进程列表中没有其他东西消耗不寻常或值得注意的RAM。
  • 重新启动后,Slab内存约为300 MB

从那时起,如果一直在监视系统,则最值得注意的是Slab内存以每天约5 GB的速率直线增长。由free和报告的可用内存/proc/meminfo减少的速度相同。Slab当前为46 GB。根据slabtop它大部分用于dentry输入:

可用内存:

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 --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  

VFS缓存压力:

cat /proc/sys/vm/vfs_cache_pressure
125

Swappiness:

cat /proc/sys/vm/swappiness
0

我知道未使用的内存是浪费的内存,因此这不一定是一件坏事(特别是考虑到44 GB显示为SReclaimable)。但是,显然机器仍然遇到问题,而且恐怕在Slab超过90 GB的几天后,同样的情况会再次发生。

问题

我有以下问题:

  • 我是否认为Slab内存始终是物理RAM,并且已经从MemFree值中减去了该数字,这是正确的吗?
  • 如此大量的牙科入口是否正常?PHP应用程序可以访问大约150万个文件,但是其中大多数是归档文件,对于常规的Web流量根本无法访问。
  • 缓存的inode的数量比缓存的dentries的数量低得多的事实可能是什么解释,它们是否应该以某种方式不相关?
  • 如果系统遇到内存故障,内核是否应该不自动释放某些内存?没有发生这种情况的原因可能是什么?
  • 有什么方法可以“查看”牙科缓存,以查看所有这些内存(即正在缓存的路径是什么)吗?也许这表明某种内存泄漏,symlink循环,或者实际上是PHP应用程序做错的事情。
  • PHP应用程序代码以及所有资产文件都是通过GlusterFS网络文件系统挂载的,这与它有关系吗?

请记住,我不能以root用户身份进行调查,只能以普通用户身份进行调查,并且管理员拒绝提供帮助。他甚至不会运行典型的echo 2 > /proc/sys/vm/drop_caches测试来查看Slab内存是否确实可回收。

我们将不胜感激任何对可能发生的事情以及我将如何进行进一步调查的见解。

更新

一些进一步的诊断信息:

坐骑

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

挂载信息:

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

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(可能很长)cat /proc/self/mountinfo
马修·伊夫

@MIfe我已经更新了问题,两个输出都已附加。
Wolfgang Stengel

我在这里的感觉可能与NFS dentry缓存有关。出于兴趣,您可以逃跑cat /etc/nfsmount.conf。另外,您的直接目录中是否有包含许多文件的目录?
马修·伊夫

1
好吧,由于vfs_cache_pressure> 100,内核应优先回收dentrie缓存。这很容易是一个错误,2.6.32是相当老的内核,即使使用RedHat反向端口补丁也是如此。顺便说一句,什么是确切的内核版本?
poige

2
(您的系统管理员听起来很糟糕。它给我们起了一个不好的名字)
ewwhite

Answers:


14

我是否认为Slab内存始终是物理RAM,并且已经从MemFree值中减去了该数字,这是正确的吗?

是。

如此大量的牙科入口是否正常?PHP应用程序可以访问大约150万个文件,但是其中大多数是归档文件,对于常规的Web流量根本无法访问。

是的,如果系统没有内存压力。它必须将内存用于某些用途,并且在您的特定使用模式中,这可能是使用该内存的最佳方法。

缓存的inode的数量比缓存的dentries的数量低得多的事实可能是什么解释,它们是否应该以某种方式不相关?

许多目录操作将是最可能的解释。

如果系统遇到内存故障,内核是否应该不自动释放某些内存?没有发生这种情况的原因可能是什么?

应该,而且我想不出它不会的任何原因。我不确信这实际上是错误的。我强烈建议升级您的内核或进一步增加vfs_cache_pressure。

有什么方法可以“查看”牙科缓存,以查看所有这些内存(即正在缓存的路径是什么)吗?也许这表明某种内存泄漏,symlink循环,或者实际上是PHP应用程序做错的事情。

我不相信那里。我会寻找具有大量条目或搜索或遍历非常深的目录结构的目录。

PHP应用程序代码以及所有资产文件都是通过GlusterFS网络文件系统挂载的,这与它有关系吗?

绝对可能是文件系统问题。例如,可能导致文件系统错误导致无法释放牙科。


感谢您单独回答我的问题。最终,缓存压力进一步增加,并且牙科缓存的增长停止了。
Wolfgang Stengel,2014年

我还无法找到负责的程序。如果我发现更多信息,我将向其他报告此问题的人报告。
Wolfgang Stengel,2014年

1
谢谢!在我的情况下,大目录(0.25万个文件)完全是问题的原因,任何与它进行交互的东西2GB的ram都会消失在缓存中。
一些Linux Nerd 2015年

20

确认的解决方案

对于可能遇到相同问题的任何人。数据中心人员终于在今天找到了解决方案。罪魁祸首是与Libcurl捆绑在一起的NSS(网络安全服务)库。升级到最新版本解决了该问题。

此处描述了详细信息的错误报告:

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

显然,为了确定某个路径是本地路径还是在网络驱动器上,NSS正在查找不存在的文件,并测量文件系统报告所需的时间!如果您有足够数量的Curl请求和足够的内存,则这些请求都将被缓存并堆叠。


15

我碰到了这个确切的问题,虽然沃尔夫冈(Wolfgang)对原因是正确的,但仍然缺少一些重要的细节。

  • 此问题影响使用curl或libcurl进行的SSL请求,或碰巧使用mozilla NSS进行安全连接的任何其他软件。非安全请求不会触发此问题。

  • 该问题不需要并发的curl请求。只要curl调用足够频繁以超过操作系统回收RAM的努力,就会发生牙科积累。

  • NSS 3.16.0的较新版本确实包含对此的修复程序。但是,您不能通过升级NSS来免费获得该修补程序,也不必升级所有NSS。您只需要最少升级nss-softokn(对nss-utils有必需的依赖性)。为了获得好处,您需要为使用libcurl的进程设置环境变量NSS_SDB_USE_CACHE。该环境变量的存在可以跳过代价高昂的不存在的文件检查。

FWIW,我写了一个博客条目,其中包含一些背景知识/细节,以防万一有人需要它。


感谢您的精彩博文,但我想提及nss-softokn尚未在CentOS / RHEL上更新为3.16版。它将在6.6版中修复。
Strahinja Kustudic,2014年

1
感谢您的来信。也许亚马逊在托管仓库方面领先于这个(甚至是我们的要求?)。在较旧的版本(3.14-3.15)中,通过设置适当的环境变量,您仍然可以获得一半的收益。如果您有专门知识,则可以直接构建v3.16。否则,增加缓存压力并占用相关的CPU可能是获得可靠性能的最佳选择。
J. Paulding 2014年

3
这个被固定于CentOS 6.6 NSS-softokn-3.14.3-17
Strahinja Kustudic

1
只是对于希望快速解决问题的人来说很清楚:您必须同时更新nss-softokenRPM 设置NSS_SDB_USE_CACHE=YESenv var才能使curl https调用停止淹没您的dentry缓存。
史蒂夫·凯莱特

4

参见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

有数字表明,将vfs_cache_pressure设置为高于100时,可以预期会有一些显着的dentry内存回收。因此125可能太低而无法在您的情况下发生。


据我所读,仅当您没有足够的RAM来承担工作量时vfs_cache_pressure100才可以增加上述值。在这种情况下,将值设置为大于100(例如10000)将释放一些RAM。但是,这将导致整体IO变差。
米科·兰塔莱宁

3

并不是真正解释您的答案,但作为该系统的用户,您提供的信息是:

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

足以告诉我这不是您的问题,它是sysadmin提供充分解释的责任。

我不想在这里听起来无礼,但是;

  • 您缺少有关此主机角色的特定信息。
  • 主机如何确定资源优先级超出了您的范围。
  • 您不熟悉此主机,或者对该主机的存储设计和部署没有任何参与。
  • 由于您不是root用户,因此无法提供某些系统输出。

证明或解决平板分配异常是系统管理员的责任。要么您没有给我们完整地了解导致您达到此目的的完整故事(坦率地说,我对此不感兴趣),要么您的系统管理员对他认为处理此问题的方式不负责任和/或无能为力。

随便在网上告诉他一些陌生人认为他没有认真对待自己的责任。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.