系统资源不足 电脑提示可用资源不足

时间:2023-04-29 17:16/span> 作者:tiger 分类: 新知 浏览:1932 评论:0

皮一下

下了班很想躺平,不想更新,不想提升技术。只想刷短视频,看别人怎么无人出镜,复制粘贴月入三万。然后看看自己账户余额,三位数;工资单不到人均百万水平;想想马上到35岁要去送外卖,跑滴滴了;上海有房,但是孩子出生可能要成为壁橱女孩。我想想还是咬咬牙更新一下。

所以,您今天刷题了吗

一、事故经过

如题,今天的真实事件。我负责的一个自动化巡检系统,每天8点左右会定时巡检公司几千台服务器(替代人工巡检,每天为公司节省了了几百工时),如磁盘空间,进程状态,数据库连通状态,中间件连通状态等指标检测,8点钟刚好是人肉挤地铁通勤时间。

这套系统运行了3个月,除了今天其余时刻都准时发出报告。接到领导电话,责问早已习以为常,只是惊讶:不可能是我的问题啊,代码三个月没改了,肯定是其他同事造成的。没办法,锅总要先甩的。

立马拿出电脑,地铁小马扎一坐,VPN各种软件登录一通,10分钟就过去了。第一时间就是到应用程序日志去排查,发现sql查询执行了一部分,然后中断了,但是没有panic。后面又去致命错误日志文件查看。好家伙,8点2分出现了Out of memory: Kill process 14298 (mysqld) score 332 or sacrifice child

mysqld进程被杀死了,但是杀死的mysqld只占用了4.5G内存,这台机器共32G内存,也不至于会OOM啊,后来在全局搜索Out of memory 找到了另外一条大鱼(这里不便截图),另外一个进程也是被杀死,发现这个进程占用的内存更大,8G多。看样子不是mysqld造成的。后面的临时解决方案是把那个占用8G多内存的golang应用先迁移到了另外一台资源比较宽松的机器。

这次终于体验到golang的跨平台的便利,执行文件scp传到另外一台服务器,systemctl起下,非常快,真香。

后面又排查了程序本身有没有内存泄漏问题,该程序内存占用还是比较稳定,偶尔有波动,90%的原因归结于这台机器内存资源不够。

后面我又去搜了一些关于OOM的系统知识,供大家参考

二、什么是OOM?

OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,Linux内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽内核会把该进程杀掉。

三、为什么会OOM?

为什么会没有内存了呢?原因不外乎有两点:

1)分配的少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。

2)应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出。

内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用。

内存溢出:申请的内存超出了JVM能提供的内存大小,此时称之为溢出。

在之前没有垃圾自动回收的日子里,比如C语言和C++语言,我们必须亲自负责内存的申请与释放操作,如果申请了内存,用完后又忘记了释放,比如C++中的new了但是没有delete,那么就可能造成内存泄露。偶尔的内存泄露可能不会造成问题,而大量的内存泄露可能会导致内存溢出。

而在Java语言中,由于存在了垃圾自动回收机制,所以,我们一般不用去主动释放不用的对象所占的内存,也就是理论上来说,是不会存在“内存泄露”的。但是,如果编码不当,比如,将某个对象的引用放到了全局的Map中,虽然方法结束了,但是由于垃圾回收器会根据对象的引用情况来回收内存,导致该对象不能被及时的回收。如果该种情况出现次数多了,就会导致内存溢出,比如系统中经常使用的缓存机制。Java中的内存泄露,不同于C++中的忘了delete,往往是逻辑上的原因泄露。

3)golang最常见的OOM情况

golang内存分配,内存溢出和GC在我的一篇面试总结里面很较细节的描述,左侧目录栏拉到内存相关。

4)JAVA最常见的OOM情况有以下三种:

java.lang.OutOfMemoryError: Java heap space ------>java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。

java.lang.OutOfMemoryError: PermGen space ------>java永久代溢出,即方法区溢出了,一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。

java.lang.StackOverflowError ------> 不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。

四、OOM分析工具

1)java常用heapdump,jps,jstat,jmap

2)golang常用pprof

文章评论