문제
커널 2.6.32 및 128GB 물리적 RAM이있는 CentOS 시스템은 며칠 전에 문제가 발생했습니다. 담당 시스템 관리자는 PHP-FPM 응용 프로그램이 스와핑으로 인해 더 이상 요청에 적시에 응답 free
하지 않았으며 메모리가 거의 남아 있지 않다는 것을 알고 기계를 재부팅하기로 결정했습니다.
여유 메모리는 Linux에서 혼란스러운 개념이 될 수 있으며 재부팅은 아마도 잘못된 일이라는 것을 알고 있습니다. 그러나 언급 된 관리자는 PHP 응용 프로그램 (내 책임)을 비난하고 더 이상 조사를 거부합니다.
내가 스스로 알아낼 수있는 것은 이것입니다 :
- 다시 시작하기 전에 사용 가능한 메모리 (버퍼 및 캐시 포함)는 수백 MB에 불과했습니다.
- 다시 시작하기 전에
/proc/meminfo
약 90GB (예, GB)의 Slab 메모리 사용량을보고했습니다. - 다시 시작한 후, 사용 가능한 메모리는 119GB로, 한 시간 내에 약 100GB로 줄어 듭니다. RES 열이 맨 위에 있습니다 (PHP 응용 프로그램의 특성상 몇 달 동안이 방법을 사용하는 것이 합리적입니다). 프로세스 목록에 비정상적이거나 주목할만한 양의 RAM을 소비하는 다른 것은 없습니다.
- 다시 시작한 후 Slab 메모리는 약 300MB였습니다.
그 이후로 시스템을 모니터링 해 왔으며, 특히 Slab 메모리는 하루 약 5GB의 속도로 직선으로 증가하고 있습니다. 에 의해보고 된 여유 메모리 free
와 /proc/meminfo
같은 비율로 감소한다. 슬래브는 현재 46GB입니다. 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
교환 :
cat /proc/sys/vm/swappiness
0
사용하지 않는 메모리가 메모리 낭비라는 것을 알고 있으므로 이것이 반드시 나쁜 것은 아닙니다 (특히 44GB가 SReclaimable로 표시되는 경우). 그럼에도 불구하고 분명히 기계는 문제를 겪었고, Slab이 90GB를 초과 할 때 며칠 안에 같은 일이 다시 일어날 것을 두려워합니다.
질문
다음과 같은 질문이 있습니다.
- 슬래브 메모리가 항상 실제 RAM이고 그 숫자가 MemFree 값에서 이미 뺀다 고 생각하는 것이 맞습니까?
- 그런 많은 수의 치 열기 항목이 정상입니까? PHP 응용 프로그램은 약 1.5M 파일에 액세스 할 수 있지만 대부분은 아카이브이며 일반 웹 트래픽을 위해 전혀 액세스하지 않습니다.
- 캐시 된 inode의 수가 캐시 된 덴 트리의 수보다 훨씬 적다는 사실에 대한 설명은 무엇일까요?
- 시스템에 메모리 문제가 발생하면 커널이 일부 덴 트리를 자동으로 해제하지 않아야합니까? 이것이 일어나지 않는 이유는 무엇입니까?
- 이 모든 메모리가 무엇인지 (즉, 캐시되는 경로가 무엇인지) 덴 트리 캐시를 “찾아 보는”방법이 있습니까? 아마도 이것은 일종의 메모리 누수, symlink 루프 또는 실제로 PHP 응용 프로그램이 잘못하고있는 것을 가리 킵니다.
- 모든 애셋 파일뿐만 아니라 PHP 응용 프로그램 코드도 GlusterFS 네트워크 파일 시스템을 통해 마운트됩니다.
루트 사용자는 일반 사용자로만 조사 할 수 없으며 관리자는 도움을 거부한다는 점을 명심하십시오. 그는 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
답변
슬래브 메모리가 항상 실제 RAM이고 그 숫자가 MemFree 값에서 이미 뺀다 고 생각하는 것이 맞습니까?
예.
그런 많은 수의 치 열기 항목이 정상입니까? PHP 응용 프로그램은 약 1.5M 파일에 액세스 할 수 있지만 대부분은 아카이브이며 일반 웹 트래픽을 위해 전혀 액세스하지 않습니다.
예, 시스템에 메모리가 부족하지 않은 경우 그것은 무언가를 위해 메모리를 사용해야하며, 특정 사용 패턴에서 이것이 해당 메모리를 사용하는 가장 좋은 방법 일 수 있습니다.
캐시 된 inode의 수가 캐시 된 덴 트리의 수보다 훨씬 적다는 사실에 대한 설명은 무엇일까요?
많은 디렉토리 조작이 가장 가능성있는 설명입니다.
시스템에 메모리 문제가 발생하면 커널이 일부 덴 트리를 자동으로 해제하지 않아야합니까? 이것이 일어나지 않는 이유는 무엇입니까?
그것은해야하며, 그렇게하지 않을 이유를 생각할 수 없습니다. 이것이 실제로 잘못되었다는 것을 확신하지 못합니다. 커널을 업그레이드하거나 vfs_cache_pressure를 더 높이는 것이 좋습니다.
이 모든 메모리가 무엇인지 (즉, 캐시되는 경로가 무엇인지) 덴 트리 캐시를 “찾아 보는”방법이 있습니까? 아마도 이것은 일종의 메모리 누수, symlink 루프 또는 실제로 PHP 응용 프로그램이 잘못하고있는 것을 가리 킵니다.
나는 믿지 않는다. 터무니없이 많은 항목이 있거나 디렉토리가 검색되거나 탐색되는 디렉토리 구조가 깊은 디렉토리를 찾습니다.
모든 애셋 파일뿐만 아니라 PHP 응용 프로그램 코드도 GlusterFS 네트워크 파일 시스템을 통해 마운트됩니다.
확실히 파일 시스템 문제 일 수 있습니다. 예를 들어, 덴트 리가 해제되지 않는 파일 시스템 버그가있을 수 있습니다.
답변
확인 된 솔루션
같은 문제가 발생할 수 있습니다. 데이터 센터 직원들은 오늘 마침내 그것을 알아 냈습니다. 범인은 Libcurl과 함께 번들로 제공되는 NSS (Network Security Services) 라이브러리였습니다. 최신 버전으로 업그레이드하면 문제가 해결되었습니다.
세부 사항을 설명하는 버그 보고서는 다음과 같습니다.
https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=1044666
분명히 어떤 경로가 로컬 또는 네트워크 드라이브에 있는지 확인하기 위해 NSS는 존재하지 않는 파일을 찾고 파일 시스템이 다시보고하는 데 걸리는 시간을 측정했습니다! Curl 요청이 많고 메모리가 충분하면 이러한 요청이 모두 캐시되어 쌓입니다.
답변
나는이 정확한 문제에 부딪 쳤고 볼프강은 원인에 대해 정확하지만 중요한 세부 사항이 누락되었습니다.
-
이 문제는 curl 또는 libcurl로 수행 된 SSL 요청 또는 보안 연결을 위해 mozilla NSS를 사용하는 다른 소프트웨어에 영향을줍니다. 비보안 요청은 문제를 유발하지 않습니다.
-
이 문제에는 동시 컬 요청이 필요하지 않습니다. 컬 호출이 RAM을 회수하려는 OS의 노력을 능가 할만큼 자주 발생하는 한, 치열 축적이 발생합니다.
-
NSS의 최신 버전 인 3.16.0에는 이에 대한 수정 사항이 포함되어 있습니다. 그러나 NSS를 업그레이드해도 무료로 수정 사항을 얻을 수 없으며 모든 NSS를 업그레이드 할 필요는 없습니다. 최소한 nss-utilokn (nss-utils에 대한 필수 종속성) 만 업그레이드하면됩니다. 그리고 이점을 얻으려면 libcurl을 사용중인 프로세스에 환경 변수 NSS_SDB_USE_CACHE를 설정해야합니다. 해당 환경 변수가 존재하면 값 비싼 존재하지 않는 파일 검사를 건너 뛸 수 있습니다.
FWIW, 나는 누군가가 그것을 필요로 할 경우를 대비하여 조금 더 배경 / 세부 사항이 있는 블로그 항목 을 작성 했습니다.
답변
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가 너무 낮아서 귀하의 경우에는 발생할 수 없습니다.
답변
답변에 대한 설명은 아니지만이 시스템의 사용자로서이 정보를 제공했습니다.
cat /proc/meminfo
MemTotal: 132145324 kB
...
SReclaimable: 44561644 kB
SUnreclaim: 1678736 kB
이것이 귀하의 문제 가 아니며 적절한 설명을 제공하는 sysadmin의 책임 이 아님 을 알려주기에 충분합니다 .
나는 무례하게 들리고 싶지 않지만;
- 이 호스트의 역할에 대한 특정 정보가 부족합니다.
- 호스트가 리소스 우선 순위를 정하는 방법은 범위를 벗어납니다.
- 이 호스트에서 스토리지의 설계 및 배포에 익숙하지 않거나 관련이 없습니다.
- 루트가 아니기 때문에 특정 시스템 출력을 제공 할 수 없습니다.
슬래브 할당 이상을 정당화하거나 해결하는 것은 시스템 관리자의 책임 입니다. 당신이 우리에게이 사실을 알리는 전체 사가에 대한 완전한 그림을 제공하지 않았거나 (솔직히 내가 관심이없는) 시스템 관리자 가이 문제를 처리하는 방식에 무책임하고 무능하게 행동하고 있습니다.
인터넷상에서 임의의 낯선 사람이 자신의 책임을 진지하게 받아들이지 않는다고 생각한다고 자유롭게 말하십시오.