APP下载

排查服务器内存异常故障

2019-12-16河南刘进京

网络安全和信息化 2019年12期
关键词:磁盘内核命令

河南 刘进京

单位的一台服务器出现故障,导致正常的业务无法进行。该服务器主要进行市场数据评估分析,分析程序使用Java 开发。该服务器一直运行比较正常,使用的是CentOS 6.X系统,因为近几日数据量大增的缘故,才出现“罢工”问题。

登录到该服务器上,执行“dmesg”命令,查看系统运行信息。在其中发现“Out of memory:Kill process 31076(Java)”,“oom_adj=0,oom_score_adj=0”等内容,说明Java 进程被系统终结,造成该分析系统无法正常运作的问题。

故障排查

根据提示信息中的“Out of memory”字样,说明这是因为Java 进程大量申请系统内存资源,导致内存溢出,才被系统自动关闭。

我 们知道,在Linux 内核中存在“Out of Memory killer”管理机制,当系统内存低于警戒线时,该管理机制就会被自动激活,系统会根据实际情况,挑选并关闭合适的进程,来释放更多的内存,保证系统可以正常运行。

执行“free -m”命令,查看内存使用情况,发现该机总内存为32GB,但是可用内存却不足500MB,而且Cache和Buffer 的数值都比较低,说明系统内存消耗的很大,可能因为该分析系统使用的内存量比较高,所以系统就将对应的Java 进程关闭。

“Out of Memory killer”机制是系统在内存不足的情况下采取的应对策略,该机制会使用一套启发式算法,来计算所有进程的分数,对于得到最高的进程来说,其占用的内存量就最高,系统就会将其关闭。

在正常情况下,系统内核会根据应用程序的要求来按需分配内容,但是不同的应用程序并不会将分配的内存全部用完。对于这些“剩余”的内存来说,系统可以对其合理利用。但是这些内存量属于不同的进程,系统如果直接回收的话,实现起来是比较繁琐的。

为此系统会采用“Over-Commit memory”(即过度分配内存)的方法,来提高内存的整体使用率。即系统会判定各进程不会同时使用并用完分配给它们的内存上限。在一般情况下,系统这样管理内存是没有问题的。

但是,如果大多数应用程序都用完了系统分配给其的内存后,就会造成这些内存消耗量之和大于物理内存容量的情况,进而就会出现系统可用内存急速降低甚至不堪使用的情况,即没有内存页能够分配给进程。

而系统为了保证正常运作,必须停止一些消耗内存的“大户”,才可以释放出更多的内存。这样就必然激活“Out of Memory killer”机制,利用对应的启发式算法,来关闭合适的进程。

在本例中,因为Jave 进程占用的内存量比较大,自然成了管控的目标。对于“Out of Memory killer”机制来说,其实际上是根据不同进程的打分情况,来决定其是否可以被关闭。对于Root 级别的进程来说,因为其地位比较重要,所以一般不会被轻易关闭,在评分上会得到3%的“优待”。用户空间的进程可以对和其关联的“oom_adj”内核参数,来调整得分情况,降低其被系统关闭的可能性。

例如对于上述Java 进程来说,可以执行“cat/proc/31076/oom_score”命令,来显示显示其当前的得分数。执行“echo -10 >/proc/31076/oom_score_adj”命令,可以调整与其对应的“oom_score_adj”参数,来降低评分值,这里将“oom_score_adj”参数的值设置为“-10”,您可以根据根据实际情况进行调整。之后再执行“cat/proc/31076/oom_score”命令,可以看到其评分降低了,这样就降低了其被系统关闭的概率。

故障解决

根据以上分析,可以看到正是因为近来数据量的激增,导致该分析系统消耗的内存量很大,远超平时的内存使用量,大量的占用可用内存,才被系统使用“Out of Memory killer”机制关闭。

执 行“cat/proc/sys/overcommit_memory/”命令,发现其数值为1,对于“overcommit_memory”参数来说,可以对“Out of Memory killer”机制进行控制,如果将其值设置为“0”,表示在用户申请内存时,系统会对剩余内存进行检测,如果发现可用内存无法满足要求,就会申请失败。

如果将其值设置为“1”,表示在用户申请内存时,系统不进行可用内存量的检测,直到使用的内存超过可用内存为止。如果将其值设置为“2”,表示当用户一次申请的内存大小不允许超过可用内存值。这里为保证系统正常运行,最好将其设置为“0”。执行“sysctl -w vm.overcommit_memory=0”,“echo " vm.overcommit_memory=0">>/etc/sysctl.conf”命令,将该参数的值设置为“0”。这样可以最大限度的避免可用内存过低,导致系统自行关闭目标进程的问题。

可以看出,该故障就是因为内存问题引发。为了保证该服务器顺畅运行,很有必须对其内存使用情况进行合理优化。

例如在执行“free -m”命令时,会看到“cache”和“buffers”参数,这两者其实都是系统用来保存曾经打开的文件信息之用,当系统需要读取对应的文件时,会从“cached”和“buffers”内存区域中查找。如果可以找到的话,就直接将数据读出,发送给目标程序,如果没有的话,才从磁盘中读取数据。利用系统的缓存机制,可以有效提高读写性能。

对 于Buffers 来 说,表示块设备所占用的缓存页,这包括直接读取块设备、文件系统元数据等使用的缓存页。Cached 表示普通文件所占用的缓存页,其将读取过的数据保存起来,在重新读取时如果发现需要的数据,将不需要重新读取磁盘。对于Cached 来说,会将缓存的数据按照读取的频度进来管理,将最频繁读取的数据保存到易于找到的位置,将不容易读取的内容排列在后面,对于最不经常读取的数据则进行删除。对于Linux来说,提供了自动释放Cache的机制,但是为了提高灵活性,可以手动处理。

例如执行以下命令:

可以分别释放Page Cache,释放文件节点缓存和目录项缓存,释放Page cache、dentries 和nodes 缓存。

注意,在手动释放之前,可以执行“sync”命令,将所有未写的系统缓冲区写到磁盘中,其中包含已修改的i-node、已延迟的块 I/O 和读写映射文件。Linux 使用的基于分页存取的内存管理机制为了充分利用物理内存,系统就会根据情况将物理内存中不常用的数据块自动交换到SWAP 虚拟内存之中。

在系统内核参数中,“swappiness”的值掌控使用SWAP 分区的比例。执行“cat/proc/sys/ym/swappiness”命令,可以查看该参数的值,其默认为60,表示内存使用到40%的时候,才开始使用虚拟内存。

为了尽可能的使用内存,可以将它修改为合适的值,例如,执行“sysctl vm.swappiness=20”命令,将其设置为20,这样的话,只有当内存使用到80%时,才可以开始使用虚拟内存等。而如果想永久保存修改的话,则可以打开“/etc/sysctl.conf”文件,并在其中添加“vm.swappiness=x”行即可,其中的“x”表示的是具体的数值。

对于Linux 文件系统来说,会使用Page cache 来优化文件读写操作。对于读写的数据都缓存到Page Cahce中,在执行上述“free -m”命令时,在“Cached”中显示的就是该缓存信息。在读文件时,会现在Page Cache 中查找,如果找到就直接读取,否则的话再从磁盘读取文件,并写入到Page Cahce 中。在写入数据时,会先将其写入到Page Cache,并打上“dirty”标记,写入缓存中的数据会定期批量保存到文件系统中。

对于Page Cache 来说,系统内核参数“vm.dirty_background_ratio”的作用是,当缓存中的带有“Dirty”标记的页的数量达到了系统内存的某个比率时,系统才将缓存的数据页异步写入磁盘。

例如执行“sysctl -w vm.dirty_background_ratio=5”命令,将其设置为5%,就是一个比较合理的数值。内核参数“vm.dirty_ratio”的作用是当缓存的脏页数量达到系统内存某个比率时,系统必须将缓存脏页刷入磁盘,这主要是为了避免丢失数据。执行“sysctl-w vm.dirty_ ratio=10”命令,将该比率设置为10%,则是比较合理的数值。

如果该值过大,就会很容易造成当系统将脏页缓存刷入磁盘时,引发其他程序在读写数据时触发I/O 阻塞的情况。

猜你喜欢

磁盘内核命令
多内核操作系统综述①
管理Windows10的PowerShell命令行使用记录
强化『高新』内核 打造农业『硅谷』
活化非遗文化 承启设计内核
它的好 它的坏 详解动态磁盘
安装和启动Docker
创建虚拟机磁盘方式的选择
解决Windows磁盘签名冲突
微软发布新Edge浏览器预览版下载换装Chrome内核
移防命令下达后