线上服务器内存分析及问题排查

转载自  线上服务器内存分析及问题排查

平常的工作中,在衡量服务器的性能时,经常会涉及到几个指标,load、cpu、mem、qps、rt等。每个指标都有其独特的意义,很多时候在线上出现问题时,往往会伴随着某些指标的异常。大部分情况下,在问题发生之前,某些指标就会提前有异常显示。

在第一篇文章中,我们介绍了一个重要的指标就是负载(Load),其中我们提到Linux的负载高,主要是由于CPU使用、内存使用、IO消耗三部分构成。任意一项使用过多,都将导致服务器负载的急剧攀升。本文是该系列的第三篇,来分析一下影响机器负载的几个原因中的第二项,内存使用。

 

什么是内存

内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。计算机中所有程序的运行都是在内存中进行的,因此内存的性能对计算机的影响非常大。

内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。

物理内存

物理内存指通过物理内存条而获得的内存空间。即随机存取存储器(random access memory,RAM),是与CPU直接交换数据的内部存储器,也叫主存(内存)。

虚拟内存

虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换(也就是说,当物理内存不足时,可能会借用硬盘空间来充当内存使用)。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型程序的编写变得更容易,对真正的物理内存(例如RAM)的使用也更有效率。

Swap分区

Swap分区(即交换区)在系统的物理内存不够用的时候,把硬盘空间中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap分区中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到内存中。

程序运行时的数据加载,线程并发,I/O缓冲等等,都依赖于内存,可用内存的大小,决定了程序是否能正常运行以及运行的性能。

查看内存使用情况

在Linux机器上,有多个命令都可以查看机器的内存信息。其中包括free、top等。

free命令

free命令可以显示Linux系统中空闲的、已用的物理内存swap分区以及被内核缓冲区内存。在Linux系统监控的工具中,free命令是最经常使用的命令之一。

$freetotal       used       free     shared    buffers     cached
Mem:       8388608    2926968    5461640          0          0    1654392
-/+ buffers/cache:    1272576    7116032
Swap:     16777208          0   16777208

上图中,一共有3行6列数据,行数据的意义如下: Mem 行是内存的使用情况。 -/+ buffers/cache 行是物理内存的缓存统计情况。 Swap 行是交换空间的使用情况。

前面分别介绍过了物理内存和Swap分区。这里再介绍一下buffers和cache。

buffer与cache的区别

A buffer is something that has yet to be "written" to disk.

A cache is something that has been "read" from the disk and stored for later use.

简单点说:

buffers 就是存放要输出到disk(块设备)的数据,缓冲满了一次写,提高IO性能(内存 -> 磁盘)

cached 就是存放从disk上读出的数据,常用的缓存起来,减少IO(磁盘 -> 内存)

buffer 和 cache,两者都是RAM中的数据。简单来说,buffer是即将要被写入磁盘的,cache是被从磁盘中读出来的。

介绍完了buffer和cache的区别,接下来分析下free命令查询到的数据。

Mem行

             total       used       free     shared    buffers     cached
Mem:       8388608    2926968    5461640          0          0    1654392

这一行展示物理内存的整体情况。

Total:8388608。表示物理内存总大小。

Used :2926968。表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。

Free :5461640。表示未被分配的内存。

Shared:0。共享内存,一般系统不会用到。

Buffers:0。系统分配但未被使用的buffers 数量。

Cached:1654392。系统分配但未被使用的cache 数量。

total(Mem) = used(Mem) + free(Mem)

-/+ buffers/cache 行

             total       used       free     shared    buffers     cached
-/+ buffers/cache:    1272576    7116032

Used:1272576。 表示实际使用的buffers 与cache 总量,也是实际使用的内存总量。

Free:7116032。 未被使用的buffers 与cache 和未被分配的内存之和,这就是系统当前实际可用内存。

used(-/+ buffers/cache) = used(Mem) - cached(Mem) - buffers(Mem)

free(-/+ buffers/cache) = free(Mem) + cached (Mem)+ buffers(Mem)

Swap 行

$freetotal       used       free     shared    buffers     cached
Swap:     16777208          0   16777208

Total:16777208。Swap内存总大小。

Used:0。表示已分配的Swap大小。

Free:16777208。表示未被分配的内存。

接下来,再来整体看一下数据

$freetotal       used       free     shared    buffers     cached
Mem:       8388608    2926968    5461640          0          0    1654392
-/+ buffers/cache:    1272576    7116032
Swap:     16777208          0   16777208

机器上实际可用内存大小:

   Free(-/+ buffers/cache)= Free(Mem)+buffers(Mem)+Cached(Mem);7116032 = 5461640 + 0+ 1654392

已经分配的内存大小:

   Used(Mem) = Used(-/+ buffers/cache)+ buffers(Mem) + Cached(Mem)2926968 = 1272576 + 0 + 1654392

物理内存总大小

   total(Mem) = used(-/+ buffers/cache) + free(-/+ buffers/cache)8388608 = 1272576 + 7116032

总结一下,整个机器的总内存大小8388608,其中已经分配的内存有2926968,还未分配的内存有5461640。而分配的2926968中,有1654392还没有使用,有1272576已经用掉了。当前机器中还有7116032内存可以使用。

free命令参数

-m 以M为单位显示内存

$free -mtotal       used       free     shared    buffers     cached
Mem:          8192       2802       5389          0          0       1559
-/+ buffers/cache:       1243       6948
Swap:        16383          0      16383

-g 以G为单位显示内存

$free -gtotal       used       free     shared    buffers     cached
Mem:          8          2          5         0         0           1
-/+ buffers/cache:       1          6
Swap:        16          0          16

-s 2持续的观察内存的状况,每隔2秒打印一次

$free -s 2total       used       free     shared    buffers     cached
Mem:       8388608    2873128    5515480          0          0    1600588
-/+ buffers/cache:    1272540    7116068
Swap:     16777208          0   16777208total       used       free     shared    buffers     cached
Mem:       8388608    2873168    5515440          0          0    1600628
-/+ buffers/cache:    1272540    7116068
Swap:     16777208          0   16777208

除了free ,还可以在Linux下可以使用/proc/meminfo文件查看操作系统内存的使用状态,其实,free命令的内容也是来自于/proc/meminfo文件。

top命令

top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。

在前面两篇文章中介绍过使用top命令查看Load Avg和CPU利用率。top还会打印的一部分信息就是内存情况。

top - 17:49:32 up 2 days,  6:25,  1 user,  load average: 0.01, 0.09, 0.12
Tasks:  30 total,   1 running,  29 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.1%us,  0.0%sy,  0.0%ni, 88.0%id,  3.8%wa,  0.0%hi,  0.0%si,  8.1%st
Mem:   8388608k total,  2884716k used,  5503892k free,        0k buffers
Swap: 16777208k total,        0k used, 16777208k free,  1612080k cachedPID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND85690 admin     20   0 5138m 1.1g  47m S  2.3 13.9  93:28.92 java

上面的Mem行和Swap行展示的就是内存的使用情况。并且也会按照进行展示不同进程的内存占用情况。十分好用。

 

Java Web应用内存占用飙高排查思路

JVM以一个进程(Process)的身份运行在Linux系统上,对于Linux来说,JVM不过是一个具有自助管理内存的乖孩子而已。

一般在应用启动时都可以通过JVM参数来设置JVM内存的大小。如果超过这个限制就会抛出异常。所以,我们比较常见的内存占用过高问题,最显著的现象就是抛出各种OutOfMemoryError。

有一种可能导致直接内存,也就是Linux的物理内存过高的情况,就是NIO的使用。NIO引入了一种基于通道与缓冲区的IO方式,他可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。

所以,在使用NIO的时候,要特别小心,避免导致机器内存被挤满。

导致JVM中内存占用飙高的原因可能有很多。最常见的就是内存泄露。

内存泄露排查思路

1、使用top命令,查看占用内存较高的进程ID。

➜  ~ topPID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
3331 admin     20   0 7127m 2.6g  38m S 10.7 90.6  10:20.26 java

发现PID为3331的进程占用内存 90.6%。而且是一个Java进程,基本断定是程序问题。

2、使用jmap查看内存情况,并分析是否存在内存泄露。

jmap -heap 3331:查看java 堆(heap)使用情况jmap -histo 3331:查看堆内存(histogram)中的对象数量及大小jmap -histo:live 3331:JVM会先触发gc,然后再统计信息jmap -dump:format=b,file=heapDump 3331:将内存使用的详细情况输出到文件

得到堆dump文件后,可以进行对象分析。如果有大量对象在持续被引用,并没有被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324925.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ssl1762-工厂的烦恼【图论,最短路变形(最长路)】

题目 一个有向图,求它的最长路。 输入 5 5 1 2 2 2 4 9 1 3 7 3 4 1 4 5 6 输出 17 解题思路 就是最短路的算法进行一些更改。不过注意加判断 if (a[i][k] && a[k][j]) 因为最短路如果有一个不能连不会对结果照成影响,可最长路就不…

RabbitMQ系列教程之一:我们从最简单的事情开始!Hello World

一、简介 RabbitMQ是一个消息的代理器,用于接收和发送消息,你可以这样想,他就是一个邮局,当您把需要寄送的邮件投递到邮筒之时,你可以确定的是邮递员先生肯定会把邮件发送到需要接收邮件的人的手里,不…

红歌合唱之团结就是力量

今天,由王老师组织的班级红歌大合唱之“团结就是力量”圆满落幕!下面是整个合唱的视频,同学们个个都朝气蓬勃:以下是《团结就是力量》的全部歌词团结就是力量团结就是力量这力量是铁这力量是钢比铁还硬比钢还强向着法西斯蒂开火让…

ssl1615-Frogger【图论,最小生成树,并查集】

题目 给一个无向图,要求从点1到点2的一条路,要求这条路上的边的最大值尽量小。 输入输入 多组数据,每个数据n1行,分别是n和点的坐标 2 0 0 3 4 3 17 4 19 4 18 5 0 输出 这条路上的边的最大值 Scenario #1 Frog Di…

Servlet API

1、书写一个servlet的方式 Servlet必须直接或间接实现 javax.servlet.Servlet 接口 通过继承javax.servlet.GenericServlet 类实现跨协议的 Servlet 通过继承javax.servlet.HttpServlet实现HTTP Servlet 自己定义个servlet,然后其他的java类都继承自己写好的servlet…

EventBus In eShop -- 解析微软微服务架构eShopOnContainers(四)

引言 大家好像对分析源码厌倦了,说实在我也会厌倦,不过不看是无法分析其后面的东西,从易到难是一个必要的过程。 今天说下EventBus,前几天园里的大神已经把其解刨事件总线(Event Bus)知多少,我…

再有人问你synchronized是什么,就把这篇文章发给他。

转载自 再有人问你synchronized是什么,就把这篇文章发给他。 在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性、可见性和有序性问题,提供了一系列和并发处理相关的…

基本数据类型、包装类、String三者之间的相互转换

package com.wdl.day13;import org.junit.Test;/** 包装类的使用:* 1.java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征** 2.掌握的:基本数据类型、包装类、String三者之间的相互转换****/ public class WrapperTest {//Strin…

很简单很简单的DBHelper类

记录一个简单的DBHelper类吧&#xff0c;用的时候在上来拿&#xff01; /// <summary>/// 数据库连接工具类/// </summary>public class DBHelper{string constr "Data Source.;Initial CatalogschoolDB;Integrated SecurityTrue";private SqlConnecti…

洛谷P3371-【模板】单源最短路【SPFA】

题目 一个有向图&#xff0c;求一点到所有点的最短距离 输入 4 6 1(4个点&#xff0c;6条边&#xff0c;从1出发) 1 2 2(1点到2点有一条权值2的线) 2 3 2 2 4 1 1 3 5 3 4 3 1 4 4 输出 0 2 4 3 解题思路 这题数据非常的大 说明 时空限制&#xff1a;1000ms,128M …

DDD理论学习系列(1)-- 通用语言

1.引言 在开始之前&#xff0c;我想我们有必要先了解以下DDD的主要参与者。因为毕竟语言是人说的吗&#xff0c;就像我们面向对象编程一样&#xff0c;那通用语言面向的是&#xff1f;DDD的主要参与者&#xff1a;领域专家开发人员领域专家&#xff1a;精通业务的任何人。开发…

Java中枚举的线程安全性及序列化问题

转载自 Java中枚举的线程安全性及序列化问题 Java SE5提供了一种新的类型-Java的枚举类型&#xff0c;关键字enum可以将一组具名的值的有限集合创建为一种新的类型&#xff0c;而这些具名的值可以作为常规的程序组件使用&#xff0c;这是一种非常有用的功能。本文将深入分析枚…

Servlet 参数读取

1、配置参数读取的意义&#xff1a; 把参数提取到配置的信息中这样就大大的增加了整个代码的使用性方面后期的代码维护 需要知道&#xff0c; 在这里的参数读取仅仅是读到程序里面。 2、实现代码 package com.bjsxt.servlet;import javax.servlet.ServletException; import j…

定了!对于本周四(7.16日)抽奖活动取消简要说明,新抽奖活动暂定下周三(7.22日)...

大家好&#xff0c;我是雄雄&#xff0c;对于本周四&#xff08;7.16日&#xff09;抽奖活动取消简要说明&#xff0c;新抽奖活动暂定下周三&#xff08;7.22日&#xff09;&#xff0c;欢迎各位粉丝积极参与&#xff0c;奖品已经准备好了&#xff0c;你&#xff01;准备好了吗…

洛谷P1144-最短路计算【日常最短路,日常图论,SPFA】

题目 一个无向图&#xff0c;求点1到每个点的最短路的路径数量 输入 5 7(5个点,7条边) 1 2(表示1到2有边) 1 3 2 4 3 4 2 3 4 5 4 5 输出 &#xff08;答案mod100003&#xff09; 1 1 1 2 4 解题思路 注意这是无向图&#xff0c;然后请看数据范围 对于20%的数…

RabbitMQ系列教程之二:工作队列(Work Queues)

今天开始RabbitMQ教程的第二讲&#xff0c;废话不多说&#xff0c;直接进入话题。 (使用.NET 客户端 进行事例演示) 在第一个教程中&#xff0c;我们编写了一个从命名队列中发送和接收消息的程序。在本教程中&#xff0c;我们将创建一个工作队列&#xff0c;这个队列将用于在…

单例 (Singleton)设计模式

所谓类的单例设计模式&#xff0c;就是采取一定的方法保证在整个的软件系统中&#xff0c;对某个类只能存在一个对象实例&#xff0c;并且该类只提供一个取得其对象实例的方法。如果我们要让类在一个虚拟机中只能产生一个对象&#xff0c;我们首先必须将类的构造器的访问权限设…

面试中经常会问的智力题,来看看你会做几道

转载自 面试中经常会问的智力题&#xff0c;来看看你会做几道 下面是大部分题目来自滴滴出行2017秋招题。开始头脑风暴吧~~~ 问题 question one 有50家人家&#xff0c;每家一条狗。有一天警察通知&#xff0c;50条狗当中有病狗&#xff0c;行为和正常狗不一样。每人只能通…

你喜欢什么样的课堂?

最近看了一本书《让课堂充满幽默》&#xff0c;里面有些内容还是觉得挺有道理的。书中开头就说&#xff1a;“大量的课件、复杂的网络&#xff0c;使得老师似乎成了信息管理员和媒体播放机&#xff0c;学生则成为了被灌输的对象”&#xff0c;看后&#xff0c;内心深处反问自己…

Servlet 中文乱码处理

1、为什么使用中文乱码 我们在实现登录时候 &#xff0c;需要进行前台的数据。获得数据以后可能会出现中文乱码&#xff0c;那应该如何处理呢&#xff1f; 2、get方式和Post提交方式的区别 [1]get数据的传输是不安全的 &#xff0c;post数据传递更加安全 [2]get方式数据传递有大…