赞
踩
内存泄漏,内存黑洞问题定位
[root@VM_0_17_centos ~]# free
total used free shared buff/cache available
Mem: 1883844 376664 76136 192 1431044 1311252
Swap: 1048572 30540 1018032
通过对free查看,我们对内存的整体使用有个初步了解,并快速是否存在内存泄漏可能。
这种情况不是内存泄漏,而是系统将可用内存cache起来了。在需要的时候可以释放出来使用。
如需手动释放,可执行 echo x > /proc/sys/vm/drop_caches 将缓存释放出来。(x=1,2,3)
**是否可以控制:**如命令有效果,观察内存不再升高,为控制住。表面不是内存泄露,只是cache较大。
这种情况存在内存泄漏可能,需要继续向下分析。
/tmp目录是占用内存空间的,有时候日志或者其他临时文件过大,导致内存占用过多。
[root@VM_0_17_centos ~]# du -sh /tmp/*
0 /tmp/systemd-private-0bd2eb2d32be4029bb93736c12f9cfc6-httpd.service-93VBb6
0 /tmp/systemd-private-0bd2eb2d32be4029bb93736c12f9cfc6-ntpd.service-s017JD
0 /tmp/systemd-private-5245a0f476c64b80895d3fe3e5c5e9e6-httpd.service-Hp8PSy
0 /tmp/systemd-private-5245a0f476c64b80895d3fe3e5c5e9e6-ntpd.service-yQr1bn
0 /tmp/UNIX.domain
**是否可以控制:**需要确认是否可删除。
[root@VM_0_17_centos ~]# ps aux --sort -rss | head -n 10
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 11625 0.0 0.0 97292 1732 ? Sl 14:48 0:00 /usr/local/qcloud/stargate/sgagent -d
root 11636 0.0 0.1 102348 2220 ? Ssl 14:48 0:00 /usr/local/qcloud/YunJing/YDLive/YDLive
root 11640 0.0 0.4 155208 7572 ? S 14:48 0:00 barad_agent
root 11645 0.0 0.4 158112 9192 ? S 14:48 0:04 barad_agent
root 11646 0.3 0.5 609092 11260 ? Sl 14:48 0:19 barad_agent
ps命令可以帮助我们定位分析应用进程内存泄漏。
观察RSS列,如果有进程RSS占用偏高,则存在内存泄漏可能。
需分析该程序源码是否存在泄漏可能。
[root@VM_0_17_centos ~]# cat /proc/meminfo MemTotal: 1883844 kB MemFree: 970208 kB MemAvailable: 1321960 kB Buffers: 51864 kB Cached: 405336 kB SwapCached: 0 kB Active: 272120 kB Inactive: 321892 kB Active(anon): 137008 kB Inactive(anon): 156 kB Active(file): 135112 kB Inactive(file): 321736 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 1048572 kB SwapFree: 1048572 kB Dirty: 288 kB Writeback: 0 kB AnonPages: 136824 kB Mapped: 42852 kB Shmem: 356 kB Slab: 67860 kB SReclaimable: 52156 kB SUnreclaim: 15704 kB KernelStack: 1824 kB PageTables: 3736 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 1990492 kB Committed_AS: 412576 kB VmallocTotal: 34359738367 kB VmallocUsed: 223536 kB VmallocChunk: 34359484404 kB HardwareCorrupted: 0 kB AnonHugePages: 83968 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 63480 kB DirectMap2M: 2033664 kB
meminfo中对内存的使用进行了详细的统计,我们主要关注Slab和VmllocUsed。
Slab = SReclaimable + SUnreclaim
如果内存占用偏高,且SReclaimable偏高,则表示可用内存缓存在slab系统内,需要时可回收。
如果内存占用偏高,且SUnreclaim偏高,则表示可能存在内存泄漏。需要进一步观察slabinfo
[root@VM_0_17_centos ~]# cat /proc/slabinfo
slabinfo - version: 2.1
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
mempool_flow_buf 0 0 1088 15 4 : tunables 0 0 0 : slabdata 0 0 0
mempool_rule_buf 6 6 5184 6 8 : tunables 0 0 0 : slabdata 1 1 0
mempool_rule_block 4 4 106560 1 32 : tunables 0 0 0 : slabdata 4 4 0
lw_domain 1728 1728 320 12 1 : tunables 0 0 0 : slabdata 144 144 0
isofs_inode_cache 12 12 640 12 2 : tunables 0 0 0 : slabdata 1 1 0
ext4_groupinfo_4k 420 420 136 30 1 : tunables 0 0 0 : slabdata 14 14 0
ext4_inode_cache 27060 27060 1032 15 4 : tunables 0 0 0 : slabdata 1804 1804 0
通过查看slabinfo,可以观察到具体是哪些slab的占用偏高,帮助进一步缩小问题范围。
如果占用较高,表示vmalloc分配可能存在泄漏。需要进一步分析vmallocinfo
[root@VM_0_17_centos ~]# cat /proc/vmallocinfo 0xffffc90000000000-0xffffc90000201000 2101248 alloc_large_system_hash+0x171/0x239 pages=512 vmalloc N0=512 0xffffc90000201000-0xffffc90000302000 1052672 alloc_large_system_hash+0x171/0x239 pages=256 vmalloc N0=256 0xffffc90000302000-0xffffc90000304000 8192 acpi_os_map_memory+0xea/0x142 phys=fed00000 ioremap 0xffffc90000304000-0xffffc90000307000 12288 acpi_os_map_memory+0xea/0x142 phys=7fffe000 ioremap 0xffffc90000307000-0xffffc90000328000 135168 alloc_large_system_hash+0x171/0x239 pages=32 vmalloc N0=32 0xffffc90000328000-0xffffc90000369000 266240 alloc_large_system_hash+0x171/0x239 pages=64 vmalloc N0=64 0xffffc90000369000-0xffffc90000372000 36864 alloc_large_system_hash+0x171/0x239 pages=8 vmalloc N0=8 0xffffc90000372000-0xffffc9000037b000 36864 alloc_large_system_hash+0x171/0x239 pages=8 vmalloc N0=8 0xffffc9000037b000-0xffffc90000380000 20480 alloc_large_system_hash+0x171/0x239 pages=4 vmalloc N0=4 0xffffc90000380000-0xffffc90000382000 8192 pci_enable_msix+0x2f1/0x430 phys=febf1000 ioremap 0xffffc90000382000-0xffffc90000384000 8192 pci_enable_msix+0x2f1/0x430 phys=febf3000 ioremap 0xffffc90000385000-0xffffc900003a6000 135168 raw_init+0x41/0x141 pages=32 vmalloc N0=32 0xffffc900003a6000-0xffffc900003a8000 8192 swap_cgroup_swapon+0x48/0x160 pages=1 vmalloc N0=1 0xffffc900003a8000-0xffffc900003ab000 12288 module_alloc_update_bounds+0x14/0x70 pages=2 vmalloc N0=2 0xffffc900003ac000-0xffffc900003ae000 8192 cirrus_device_init+0x8a/0x150 [cirrus] phys=febf0000 ioremap 0xffffc900003b0000-0xffffc900003b2000 8192 LW_VmemZeroAlloc+0x4e/0xc0 [lwconn] pages=1 vmalloc N0=1 0xffffc900003b2000-0xffffc900003b4000 8192 LW_VmemAlloc+0x4e/0xc0 [lwconn] pages=1 vmalloc N0=1
通过查看vmallocinfo,可以更详细的定位到是那个操作申请的内存过多,导致内存占用高,帮助我们定位问题原因。
linux系统中有部分内存是通过直接操作page申请的,/proc/meminfo无法统计到,这部分内存就像黑洞一样。
如果前面步骤还不能定位到问题,我们可以通过下面公式计算一下黑洞内存的大小:
黑洞内存 = MemTotal - MemFree - Active - Inactive - Slab - KernelStack - PageTables - VmallocUsed
如果计算出来黑洞内存占用过大,基本确认是黑洞内存占用导致。
目前看来导致内存黑洞主要有以下几个方面:
系统的socket收发队列积压,我们可以通过netstat命令查看
[root@VM_0_17_centos ~]# netstat -noap Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name Timer ...//省略部分 udp 0 0 0.0.0.0:67 0.0.0.0:* 3240/dnsmasq off (0.00/0/0) udp 0 0 61.170.203.43:123 0.0.0.0:* 3130/ntpd off (0.00/0/0) udp 0 0 169.254.200.1:123 0.0.0.0:* 3130/ntpd off (0.00/0/0) udp 0 0 192.168.1.1:123 0.0.0.0:* 3130/ntpd off (0.00/0/0) udp 0 0 127.0.0.1:123 0.0.0.0:* 3130/ntpd off (0.00/0/0) udp 0 0 0.0.0.0:123 0.0.0.0:* 3130/ntpd off (0.00/0/0) udp6 0 0 fe80::84cf:68ff:fe8:123 :::* 3130/ntpd off (0.00/0/0) udp6 0 0 ::1:123 :::* 3130/ntpd off (0.00/0/0) udp6 0 0 :::123 :::* 3130/ntpd off (0.00/0/0) raw6 76755840 0 :::58 :::* 7 3218/zebra off (0.00/0/0) Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 2 [ ACC ] STREAM LISTENING 27149 3225/bgpd /var/run/quagga/bgpd.vty unix 2 [ ] DGRAM 9249 1/systemd /run/systemd/notify unix 2 [ ] DGRAM 25891 2871/rsyslogd /run/systemd/journal/syslog unix 2 [ ] DGRAM 9251 1/systemd /run/systemd/cgroups-agent unix 2 [ ACC ] STREAM LISTENING 25447 3229/ospfd /var/run/quagga/ospfd.vty ...//省略部分
上面这个就是3218/zebra进程收报队列积压了76755840导致内存耗尽。systemctl stop zebra后问题解决。
**是否可以控制:**一般可控,手动停止或重启有问题的服务。
pf_packet socket收发队列积压,我们可以通过ss命令查看
[root@cpe ~]# ss -pf link
Netid Recv-Q Send-Q Local Address:Port Peer Address:Port
p_raw 10095232 0 ppp_disc:eth1 * users:(("pppd",pid=17865,fd=10))
上面这个就是17865/pppd 进程收报队列积压了10095232 导致内存消耗过多。重启pppd服务后,占用内存可以释放掉。
关于虚拟化balloon技术,简单来说就是在虚拟机中存在一个气球(balloon),气球中的内存是给宿主机使用的,虚拟机不能使用。
当宿主机需要内存时,可以请求虚拟机释放内存到气球中,也就是气球的充气膨胀。这样虚拟机的可用内存减少了,宿主机实际可用内存增大了。
反过来,虚拟机需要内存时,可以让气球放气缩小,也就是宿主机释放内存,让虚拟机有更多内存可使用。
balloon驱动就是直接alloc_pages操作内存,所以meminfo无法追踪到。
如果虚拟机上通过meminfo发现内存黑洞,有可能就是balloon导致。我们可以通过以下方法验证。
-bash-4.2# free -h //查看内存占用,有大概1.2G隐形内存占用
total used free shared buff/cache available
Mem: 1.8G 1.2G 77M 31M 488M 369M
Swap: 1.6G 69M 1.5G
-bash-4.2# rmmod vmw_balloon //卸载balloon
-bash-4.2# free -h //查看内存占用,此时被占用的1.2G内存释放出来了
total used free shared buff/cache available
Mem: 1.8G 78M 1.2G 31M 488M 1.5G
Swap: 1.6G 69M 1.5G
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。