记录一次排查解决服务器卡死的过程

· 浏览次数 : 36

小编点评

本文主要讨论了一个阿里云服务器在处理数据时出现的频繁卡死问题,并最终通过分析定位到内存泄漏的原因。文章首先描述了服务器在出现问题时的现象和影响,然后逐步分析了问题的原因和解决方案。 1. **问题描述**: - 服务器在处理数据时频繁卡死。 - 观察到服务器在某个时间点无法登录,之后通过阿里云控制台重启服务器恢复正常。 - 分析启动脚本发现存在问题,但未找到明显错误。 2. **问题定位**: - 通过分析日志和堆栈信息,发现服务器内存泄漏。 - 使用MAT工具分析内存泄漏的原因,发现一个对象占用内存过大。 - 在对象的属性中找到一个静态成员变量map,其键值对数量巨大,推测存在内存泄漏。 3. **解决方案**: - 定时清理内存,避免内存泄漏问题扩大。 - 在启动脚本中加入参数控制本地内存使用,以减少内存泄漏的影响。 - 对代码进行优化,减少内存泄漏的可能性。 总的来说,文章通过一步步排查和分析,成功找到了服务器内存泄漏的问题所在,并提出了相应的解决方案。同时,文章也提醒大家在遇到类似问题时要冷静分析,逐步定位问题,并采取合适的措施解决问题。

正文

前言

自己个人兴趣爱好,线上有一个阿里云服务器,处理数据用的,会频繁IO和分析数据。隔一段时间就会卡死(大概2个月),重启就OK。本来没当一回事,直到后来影响到赚取money了才引起重视。服务的启动脚本如下:

nohup java  -Xms512m  -Xmx1024m  -jar xxx.jar  &

当然这个脚本是有很多问题的,毕竟自己的服务器,追求的就是一个简单粗暴,怎么简单怎么来,没有那么多顾虑。但是自己埋的坑、迟早有一天哭着也要填完!

现象

突然有一天,登录服务器发现登录不上去,xshell 类似下面的提示。看起来是连接上了,但是进不去,这种情况一般要么是网卡、要么是服务器卡,我这显然是后者。通过阿里云控制台都进不去,一般这种情况等一段时间,消耗内存的应用会被杀掉,然后就能进去了。当然我这种急性子自然是选择去阿里云后台直接强制重启服务器。

服务器是能进去了,但是没有任何日志可供查询,没有堆栈信息,查看日志并没有发现oom错误(这里只能一句卧槽了)。于是修改启动脚本如下,以便下一次有类似情况可以有痕迹可寻:

nohup java  -Xms512m  -Xmx1024m  -Xlog:gc*:file=gc.log:time,uptime,level,tags -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps -jar  xx.jar &

内存的原因,自然是要关注内存。一般我们需要关注一下垃圾回收器的行为以及堆内存使用情况。-XX:+HeapDumpOnOutOfMemoryError 以及-XX:HeapDumpPath 就是指定了当发生堆内存溢出的时候,转储当时的内存文件供我们后续分析(其实观察到内存开销持续上涨,回收效果不明显,就可以用这个命令导来导出堆内存文件分析:jamp -dump:live,format=b,file=xxx.hprof)。终于是在某一天(2个月后),发现了OOM错误,如下所示。

这就很离谱了,上次我卡死直接强制重启了,nohup.out文件并没有看到OOM错误的日志,但是这次为啥出现OOM错误日志了。这个问题现在我都没搞清楚为什么,服务器是2G内存,启动脚本堆最大1G内存,完全够用哇,讲道理不可能消耗完服务器内存。难道代码还有IO等内存泄漏? 先不管了,先解决眼前的问题。既然是OOM错误,自然是要看是哪个实例占用了内存,使用MAT分析一下。(PS: JHAT 无异于大海捞针,因为类太多,他又不能把较大内存的排序,然后OQL又不能支持通配符,就无解,还是MAT香)。MAT分析报告如下:

可以看到有一个大对象占用内存692.4M , 这基本可以锁定这个问题就出现在这个对象上了。 然后再查其中有一个属性,是一个静态成员变量map,如图所示有6291456个key。 结合代码看该变量会被业务数据依据具体情况,填充进数据,但是并没有释放的地方,so 这就是问题所在了。

解决

我这里就是简单粗暴的定时清理一下内存,如下所示。

因为要很久才出现OOM, 所以这个代码能用,但却是不优雅的。奈何自己的项目随便弄的,写成了屎山代码,不太好改,毕竟有一句话说的好: If your code runs in some inexplicable way, don't touch it anymore。否则将会是面对如下所示的残酷:

后话

文中有提到设置了-Xmx1024m 但是实际导致服务器2G内存卡死,可能存在的内存泄漏问题,先在启动脚本加上参数-XX:MaxDirectMemorySize=256M,控制一下本地内存,后续如果再次出现OOM 了,在继续-

nohup java  -Xms512m  -Xmx1024m  -Xlog:gc*:file=gc.log:time,uptime,level,tags -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps -XX:MaxDirectMemorySize=256M -jar  xx.jar &

大家不偷懒的话,gc日志参数,堆内存导出,这些最好都设置好!

与记录一次排查解决服务器卡死的过程相似的内容:

记录一次排查解决服务器卡死的过程

前言 自己个人兴趣爱好,线上有一个阿里云服务器,处理数据用的,会频繁IO和分析数据。隔一段时间就会卡死(大概2个月),重启就OK。本来没当一回事,直到后来影响到赚取money了才引起重视。服务的启动脚本如下: nohup java -Xms512m -Xmx1024m -jar xxx.jar &

当小白遇到FullGC

本文记录了一次排查FullGC导致的TP99过高过程,介绍了一些排查时思路,线索以及工具的使用,希望能够帮助一些新手在排查问题没有很好的思路时,提供一些思路,让小白也能轻松解决FullGC问题

软件设计模式系列之十六——命令模式

命令模式(Command Pattern)是一种行为型设计模式,旨在将请求发送者和接收者解耦,将一个请求封装为一个对象,从而允许您参数化客户端对象以进行不同的请求、排队请求或记录请求,并支持可撤销操作。 命令模式的核心思想是将一个请求包装成一个对象,包括请求的参数和接收者对象,然后客户端只需要调用该...

[转帖]记录一次前端内存泄漏排查经历

https://juejin.cn/post/6844904019983335438 对于前端的“内存泄漏”这个东西,说实话我只在书上看到过: 闭包、匿名函数和事件绑定尤其容易造成内存泄漏。 然而这些操作造成的“内存泄漏”究竟是什么样子的?如何排查?虽然很好奇,却不得而知。直到这次公司应用频繁出现浏

[转帖]记录一次spring-boot程序内存泄露排查

现象 spring boot项目jvm启动配置-Xms4g -Xmx4g,然而很不幸的是程序所占的内存越来越高,都达到了12个多G,只能临时重启服务 常用命令 jstat -class PIDjstat -compiler PIDjstat -gc PIDjstat -gccapacity PIDj

记一次ThreadLocal中的用户信息混乱问题

记录一次开发中遇到的关于 ThreadLocal 问题,场景是数据库表中的操作人总是无缘无故的被更改,排查了几遍代码才发现是 ThreadLocal 没有及时清理导致的。

容易忽视的细节:Log4j 配置导致的零点接口严重超时

本文详细的记录了一次0点接口严重超时的问题排查经历。本文以作者自身视角极具代入感的描绘了从问题定位到具体的问题排查过程,并通过根因分析并最终解决问题。整个过程需要清晰的问题排查思路和丰富的问题处理经验,也离不开公司强大的调用链、和全方位的系统监控等基础设施。

一次元数据空间内存溢出的排查记录

在应用中,我们使用的 SpringData ES的 ElasticsearchRestTemplate来做查询,使用方式不对,导致每次ES查询时都新实例化了一个查询对象,会加载相关类到元数据中。最终长时间运行后元数据出现内存溢出;

[转帖] 一次SSL握手异常,我发现JDK还有发行版区别

https://www.cnblogs.com/codelogs/p/16633704.html 简介# 最近,我们一个多机房部署的服务,调用方反馈有问题,在调用新加坡机房时正常,而调用印度机房则报SSL握手异常。 排查花了一些时间,同时也积累了一些经验,故记录一下,读完本文,你将了解到如下内容:

[转帖]耗时几个月,终于找到了JVM停顿十几秒的原因

https://www.cnblogs.com/codelogs/p/16060792.html 简介# 最近我们系统出现了一些奇怪的现象,系统每隔几个星期会在大半夜重启一次,分析过程花费了很长时间,令人印象深刻,故在此记录一下。 第一次排查# 由于重启后,进程现场信息都丢失了,所以这个问题非常难以