linux-buff/cache过大致使内存不足-程序异常

问题描述node

Linux内存使用量超过阈值,使得Java应用程序无可用内存,最终致使程序崩溃。即便在程序没有挂掉时把程序停掉,系统内存也不会被释放。shell

找缘由的过程缓存

这个问题已经困扰我好几个月了,分析过好屡次都没有找到缘由,网上查了一下该问题其余人也都遇到过,不过并无什么好的解决方案,由于项目一直没有上线,每次当内存不足时致使程序崩溃都是重启服务就行了,索性也就没花太多的时间来找问题。如今项目立刻上线了,不能在出现程序崩溃的状况了,何况仍是前置系统,更不能出现任何问题。tomcat

最开始一直认为是程序的缘由致使内存泄漏,使用jdk自带的jmap -F -dump:live,format=b,file=/usr/local/sztFront/logs/heapdump.bin命令输出过几回dump文件,经过MemoryAnalyzer分析,应用程序没有耗内存过大的变量。后台猜想是否日志输出过多致使的,毕竟是前置系统,天天的报文量特别大,日志能到达5,6个G。因此把日志接收报文关了,日志大小立刻降下来了,天天200M。程序挂掉的时间变长了,原来差很少一周就挂掉了,如今能够达到两周左右才挂掉,仍是不行,没有冲根本上解决问题。通过在网上搜索各类相关的问题,问题出如今Cached的值过大,致使系统没有能够再分配的内存空间。Cached只要用来缓存文件的,常常读写的文件会被缓存到Cached中,能够增长读写效率,该功能是Linux系统内核提供的,从2.6.16之后的核心版本才提供,也就是老版的操做系统,如红旗DC 5.0、RHEL 4.x以前的版本都没有。这就能够解释为何个人项目总挂掉了,个人项目主要就是处理文件的,因此接收和下载的文件会被缓存起来,一直耗着内存不释放,即便把程序停掉也不会释放内存。最后找到了三条执行,能够清理cached的内存app

三条指令:ui

syncthis

echo 1 > /proc/sys/vm/drop_caches
echo 2 > /proc/sys/vm/drop_caches
echo 3 > /proc/sys/vm/drop_caches操作系统

执行完这三条指令后经过free -m命令查看,free可用内存立刻增多,buff/cache列值变小,说明内存被释放了,可是不能老是手动的执行这三条指令,因此最后写了一个shell脚本,开启Linux定时任务crond,天天早上检查一次free内存,当小于4G时执行这三条命令(注:系统内容20G)。.net

注意:在执行这三条命令以前必定要先执行sync命令(描述:sync 命令运行 sync 子例程。若是必须中止系统,则运行sync 命令以确保文件系统的完整性。sync 命令将全部未写的系统缓冲区写到磁盘中,包含已修改的 i-Node、已延迟的块 I/O 和读写映射文件)rest

解决方案(手动)

1. 修改/proc/sys/vm/drop_caches,释放Slab占用的cache内存空间(参考drop_caches的官方文档):

Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free.
To free pagecache:
* echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes:
* echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes:
* echo 3 > /proc/sys/vm/drop_caches
As this is a non-destructive operation, and dirty objects are notfreeable, the user should run "sync" first in order to make sure allcached objects are freed.
This tunable was added in 2.6.16.

注意:在执行这三条命令前先执行sync命令


解决方案(自动)

一、编写shell定时任务脚本freemem.sh


#! /bin/sh
used=`free -m | awk 'NR==2' | awk '{print $3}'`
free=`free -m | awk 'NR==2' | awk '{print $4}'`
echo "===========================" >> /app/memory/logs/mem.log
date >> /app/memory/logs/mem.log
echo "Memory usage before | [Use:${used}MB][Free:${free}MB]" >> /app/memory/logs/mem.log
if [ $free -le 4000 ] ; then
                sync && echo 1 > /proc/sys/vm/drop_caches
                sync && echo 2 > /proc/sys/vm/drop_caches
                sync && echo 3 > /proc/sys/vm/drop_caches
                used_ok=`free -m | awk 'NR==2' | awk '{print $3}'`
                free_ok=`free -m | awk 'NR==2' | awk '{print $4}'`
                echo "Memory usage after | [Use:${used_ok}MB][Free:${free_ok}MB]" >> /app/memory/logs/mem.log
                echo "OK" >> /app/memory/logs/mem.log
else
                echo "Not required" >> /app/memory/logs/mem.log
fi
exit 1

二、使用crontab -e命令编辑当前用户的crontab

0 6 * * * /usr/local/tomcat/sztFileFront/bin/freemem.sh
定时任务编写参考:http://www.jb51.net/article/15008.htm


三、重启crond服务

/sbin/service crond restart

四、查看crond服务是否重启成功

/sbin/service crond status

最后,问题解决。我设定的定时任务是天天早上6点执行一次freemem.sh脚本  

相关文章
相关标签/搜索