一次生产环境服务器内存不足的排查经过

今天发现有一台线上的服务器内存报警,最近报警发现有好几次了,慎是恼火,想一探究竟,看了一下是一台16G内存的服务器,free 了一下看了一下确实是没有多少内存可用了,再看了一下都跑了一些什么应用,结果发现只跑了一个数据库跟一个跨服,当时心里就感觉16G内存不可能用完,

[[email protected] logs]#ps aux|awk ‘{sum=sum + $6};END {print sum/1024"M"}‘
4363.01M  
才使用了4g多一点

#也可以通过这段在网上找到的脚本查看
#/bin/bash                                                                                                               
for PROC in `ls  /proc/|grep "^[0-9]"`
do
  if [ -f /proc/$PROC/statm ]; then
      TEP=`cat /proc/$PROC/statm | awk ‘{print ($2)}‘`
      RSS=`expr $RSS + $TEP`
  fi
done
RSS=`expr $RSS \* 4`
echo $RSS"KB"

再看看cache也没有占用多少,那内存去哪了呢?

下载nmon 进行内存查看:

wget ## http://sourceforge.net/projects/nmon/files/nmon_linux_14i.tar.gz 
直接./nmon  
按m显示内存的使用情况
这个是我释放了后的截图

当时看着free只有几百M了,slab 占用了10G slab是什么呢,经过查询资料后的解释是

slab是Linux操作系统的一种内存分配机制。其工作是针对一些经常分配并释放的对象,如进程描述符等,这些对象的大小一般比较小,如果直接采用伙伴系统来进行分配和释放,不仅会造成大量的内存碎片,而且处理速度也太慢。而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统,从而避免这些内碎片。slab分配器并不丢弃已分配的对象,而是释放并把它们保存在内存中。当以后又要请求新的对象时,就可以从内存直接获取而不用重复初始化。

查看了一下内存信息如下:

[[email protected] logs]#cat /proc/meminfo 
MemTotal:       16100652 kB
MemFree:          254236 kB
Buffers:          169600 kB
Cached:           186728 kB
SwapCached:        10064 kB
Active:          3806092 kB
Inactive:        1064960 kB
Active(anon):    3566956 kB
Inactive(anon):   948732 kB
Active(file):     239136 kB
Inactive(file):   116228 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:        511992 kB
SwapFree:         446100 kB
Dirty:                32 kB
Writeback:            72 kB
AnonPages:       4504536 kB
Mapped:            21212 kB
Shmem:               964 kB
Slab:           10621812 kB    #slab占用的内存大小10G
SReclaimable:   10590404 kB    #slab可回收的内存大小
SUnreclaim:        31408 kB    #slab不可回收的内存大小
KernelStack:        2680 kB
PageTables:        15184 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     8562316 kB
Committed_AS:    7259324 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       65132 kB
VmallocChunk:   34359627272 kB
HardwareCorrupted:     0 kB
AnonHugePages:   4325376 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:        8176 kB
DirectMap2M:    33546240 kB

#可以通过
slabtop  查看具体是什么占用了内存,

可以统计slab内存的大小,看看是不是吻合
[[email protected] dingmh]#echo `cat /proc/slabinfo |awk ‘BEGIN{sum=0;}{sum=sum+$3*$4;}END{print sum/1024/1024}‘` MB
4917.96 MB

slab可以回收的内存是可以通过触发来自动回收的

[[email protected] logs]#sysctl  -a |grep free
vm.min_free_kbytes = 67584   #意思是说只有在系统内存不满足这个值的时候才能触发,但是等到真的到这个值的时候,基本上看不到了
vm.extra_free_kbytes = 0

[[email protected] logs]#sysctl -w vm.min_free_kbytes=1048576  
vm.min_free_kbytes = 1048576
设置成1G后,系统立马从slab上释放了5g内存

具体slab是被什么应用占用了这么大的内存,等我排查完后再做详细的记录

时间: 2024-10-21 19:40:31

一次生产环境服务器内存不足的排查经过的相关文章

生产环境服务器变慢,诊断思路和性能评估

生产环境服务器变慢,诊断思路和性能评估 整机:top 代码 public class JavaDemo2 { public static void main(String[] args) { while (true){ System.out.println(new java.util.Random().nextInt(77778888)); } } } top命令查看 [[email protected] ~]# top top - 11:28:50 up 7 min, 2 users, loa

MySQL5.5.32生产环境大内存优化配置实例

[client] port    = 3306 socket    = /tmp/mysql.sock default-character-set = utf8 #设置客户端的字符编码 [mysqld] # generic configuration options port    = 3306 socket    = /tmp/mysql.sock #*** char set *** character-set-server = utf8 #设置服务器端的字符编码              #

生产环境mysql内存溢出重启简单分析

思路 1. 查看数据库日志 2. 查看慢查询 3. 查看系统日志 4. 查看监控 2017-01-03 03:03:48 0 170103 03:03:45 mysqld_safe Number of processes running now: 0 170103 03:03:45 mysqld_safe mysqld restarted   --异常重启 [Note] /usr/sbin/mysqld (mysqld 5.6.25-log) starting as process 104767

生产环境-jvm内存溢出-jprofile问题排查

通常来说,分析堆内存快照(Heap Dump)是一个很好的定位手段 ,开启了dump的参数: -XX:+HeapDumpOnOutOfMemoryError 有了这个参数,当我们不得不面对内存溢出异常的时候会节约大量的时间.默认情况下,堆内存快照会保存在JVM的启动目录下名为java_pid<pid>.hprof 的文件里(在这里<pid>就是JVM进程的进程号) dump的内容有2G,先进行压缩打包,传输至本地(scp) tar -czvf dump.tar java_pid48

生产环境报表未生成原因排查

从log日志中抓取错误信息,如下: The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. 月初生成的报表比较多,所以会出现较大数据库访问量,大致是数据库连接缓冲池的问题. 解决办法: (1)使用JDBC URL中使用autoReconnect属性,url添加 &autoReconnect=tru

一般生产环境LINUX服务器配置

1.生产环境LINUX服务器系统版本的选择 选择CentOS6.5版本64位的LINUX操作系统 CentOS (Community Enterprise Operating System,中文意思是:社区企业操作系统)是Linux发行版之一,它是来自于红帽的Red Hat Enterprise Linux依照开放源代码规定释出的源代码所编译而成.由于出自同样的源代码,因此和红帽商业版的RHEL系统用着同样的高度稳定性.两者的不同,在于CentOS并不包含红帽的商业支持和一些RHEL商业版隐藏的

Linux环境 Java内存快速查看

最近生产环境遇到内存老是占用很大的情况,16G的内存Free的内存只剩100多M,仿佛一颗定时炸弹一般,说不定就服务Down了.于是开始网上不断的找查看内存使用的方法.现学现卖,以下通过一个例子来演示,共3步. 一.通过Top命令来查看进程情况,按Shift+M可按内存占用大小排序 二.通过ps命令查看是哪个应用 三.通过jmap命令来显示堆使用情况,jmap是jdk中自带的内存查看工具,具体使用可参考 http://www.cnblogs.com/xingzc/p/5778014.html 写

.NET C#微信公众号开发远程断点调试(本地远程调试生产环境)

最近在做微信公众号开发,由于之前没有接触过,突然发现调试不方便,不方便进行断点跟踪调试.因为微信那边绑定的服务器地址必须是公网地址,但是还是想进行断点调试(毕竟这样太方便了) 因此上网搜了一下,发现好多是使用软件之类的进行请求转发从生产环境转发请求到开发环境上,发现有的太麻烦了. 突然想到Vs有一个附加到进程的远程调试.于是玩了一把.我们直接开始(服务器上就不要使用发布版本代码了,代码和本地开发一样,不然是不能调试的) 本篇是以开发环境的Visual Studio2013旗舰版以及生产环境里阿里

利用ansible-playbook从测试环境获取tomcat中java项目新版本发布到生产环境

一.环境描述 安装有ansible的服务器:192.168.13.45 测试环境服务器:192.168.13.49 /home/app/api-tomcat/webapps/api.war为测试环境新版本war包位置 生产环境服务器:192.168.13.51 /home/app/api-tomcat/webapps/api.war为生产环境war包位置     /home/app/api-tomcat/webapps/api为生产环境项目位置 /home/app/tomcat.bak/api/