由内存溢出的思考:如何监控内存?
前记
最近在做监控系统,发现Linux的内存监控比较困难,主要是指标太多,不知道那些指标才是真正需要的,比如一开始我们就监控free命令输出的free,然而由于页缓存的原因,有些数据是不对的.恰好今天刚刚遇到系统的一个内存看似不准的问题,在调查问题时同时了解了Linux的内存设计
1.一次”内存报警异常”
1.1.问题
最近监控一直在报某些机器内存异常,内存超过了90%的使用,登上去机器用free -h
命令查看发现user部分确实很多,但通过ps -aux | sort -l 4
发现所有进程加起来的内存占用都没有user的10分之一,究竟是谁在吃内存不得而知.
1.2.排查问题机器
1.2.1.top
从top命令可以看出,目前最占用内存的进程只有supervisord,只占用了0.9%的内存,即使所有进程占用内存加起来,也占用到10-20%左右
1 |
|
1.2.2. free
通过free -h
命令可以看到 共2g内存的小机器,used已经使用了1.6g了 ,占用了80%了
1 |
|
为了了解used的主要组成,先通过man free
查看free各个字段的说明
1 |
|
可以看出used是由total -free - buffes - cache计算得出,而cache又包括了Cached和SReclaimable,,所以used=total -free -buffers - Cached - SReclaimable.
1.2.3. cat /proc/meminfo
了解了free中used的计算后我们就可以自己根据/proc/meminfo查看有什么异常值,除去了计算used的free,buffers,Cached,SReclaimable后发现有一个叫SUnreclaim的值非常可疑,这个值表明的是存在于内核中的不可回收数据结构的大小, 存在与内核的数据结构有很多,比如创建一个TCP时,内核里面就会创建一个存TCP相关数据的数据结构,一般来说这个值的比较低的,而且是要低于SReclaimable(也是存在于内核中的数据结构的大小,不过是可回收的)的,所以需要进入Sunreclaim内部,查看是什么数据结构占用了比较多的内存
1 |
|
1.2.4. slabtop
slabtop可以查看slab(存放于内核的数据结构)的使用情况,可以发现有一个叫TCP的数据结构占用了600多M的内存,根据往常的使用经验,一个正常使用的TCP链接大概占4kb左右,这样算下来是这台机器打开了161392个TCP链接,显然是不对的(即使64kb, 换算下来也要1w个请求, 当前的请求量根本没那么多).所以需要对该问题进行修复,不过由于该问题是更改TCP参数造成的,跟主题不一样,所以关于内存异常的问题的调查就到这.
1 |
|
2.要监控哪些内存
通过上面的排查后,可以比较明确的是,内存监控不是单一指标,应该用一主多辅的指标进行监控(不然Linux内存那么多指标就是摆设了….)
主要指标当然是我们常说的内存使用占比了,根据free命令中的说明,我们一般都是用free的user/total来计算,也就是((MemTotal - (MemFree + Buffers + Cached + SReclaimable)) / MemTotal),但是这个计算会漏一些数据,比如上面所说的SUnreclaim
以及/proc/meminfo里面的其他情况,同时Linux的页缓存也可能存在无法回收的情况.所以可以说这个指标也是不太准的.
那要怎么样才能把上面的情况考虑进去,尽量做一个所有服务都共有的内存监控呢,还记得free里有一个available字段,他的文档说明也说了,该字段是对一些可用内存进行统计,同时它会考虑 Page Cache 和无法回收的SUnreclaim
的内存( 假设pagecache / 2 和 SUnreclaim
/ 2 是不可回收的),最后估算出一个当前可用内存,来达到尽可能的与实际数据贴合.
所以实际的内存统计应该为( MemTotal - MemAvailable) / MemTotal,这样子会比原来的统计更加准确.
这样一来主要指标已经定下了,但考虑到他只能尽量去适配所有业务,有些业务有对某项值消耗的非常厉害,但主要指标不一定能统计到的,所以我们还要添加一些辅助指标,以完善我们的内存监控系统
SUnreclaim
,就像我们上面提到的,这个指标一般机器是不会出现的,只有涉及到tcp等问题才会导致该常数的值异常,这个异常用我们的主要指标是很难分析到的.buffer
,cached
,正常情况下的业务该值是不会有异常的,但是在涉及到一些io读写比较多的情景时,机器上面很多内存会被buffer,cached占用.3. 附录
3.1. 正常机器数据
该章节主要用于展示数据,对比与原来的数据差别3.2. free
1
2
3total used free shared buff/cache available
Mem: 2.0Gi 193Mi 921Mi 20Mi 882Mi 1.6Gi
Swap: 0B 0B 0B3.3. cat /proc/meminfo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47MemTotal: 2045852 kB
MemFree: 937856 kB
MemAvailable: 1658140 kB
Buffers: 56928 kB
Cached: 779772 kB
SwapCached: 0 kB
Active: 356800 kB
Inactive: 604076 kB
Active(anon): 121720 kB
Inactive(anon): 20808 kB
Active(file): 235080 kB
Inactive(file): 583268 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 28 kB
Writeback: 0 kB
AnonPages: 121908 kB
Mapped: 36768 kB
Shmem: 20972 kB
Slab: 104908 kB
SReclaimable: 67096 kB
SUnreclaim: 37812 kB
KernelStack: 1612 kB
PageTables: 2088 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 1022924 kB
Committed_AS: 398732 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
Percpu: 356 kB
AnonHugePages: 51200 kB
ShmemHugePages: 0 kB
ShmemPmdMapped: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB
DirectMap4k: 163812 kB
DirectMap2M: 1933312 kB
DirectMap1G: 0 kB3.4. slabtop
1
2
3
4
5
6
7
8
9
10
11
12
13OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
183456 179948 98% 0.10K 4704 39 18816K buffer_head
57036 55070 96% 0.19K 2716 21 10864K dentry
51639 51639 100% 0.19K 2459 21 9836K kmalloc-192
24684 24684 100% 0.04K 242 102 968K ext4_extent_status
17280 16530 95% 0.03K 135 128 540K kmalloc-32
17055 16817 98% 1.05K 1137 15 18192K ext4_inode_cache
15420 15420 100% 0.13K 514 30 2056K kernfs_node_cache
11520 10774 93% 0.06K 180 64 720K anon_vma_chain
11479 11416 99% 0.59K 883 13 7064K inode_cache
11136 11136 100% 0.06K 174 64 696K tcp_bind_bucket
9024 7905 87% 0.06K 141 64 564K kmalloc-64
8960 8960 100% 0.02K 35 256 140K kmalloc-16
- 本文作者:So1n
- 本文链接:http://so1n.me/2020/05/28/%E5%86%85%E5%AD%98%E7%BB%9F%E8%AE%A1/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!