How to Fix High CPU/Memory Usage for Linux

CPU占用高的问题

最近一段时间 某台服务器上的一个应用总是隔一段时间就自己挂掉 用top看了看 从重新部署应用开始没有多长时间CPU占用上升得很快

排查步骤

  1. 使用top 定位到占用CPU高的进程PID top, 按 P,以 CPU 占用率大小的顺序

  2. 通过ps aux | grep PID命令

  3. 获取线程信息,并找到占用CPU高的线程 ps -mp pid -o THREAD,tid,time | sort -rn

  4. 打印线程的堆栈信息 到了这一步具体看堆栈的日志来定位问题了 jstack pid |grep tid -A 30

例子

  1. top 可以看出PID 733进程 的占用CPU 172%

  2. 查找进程733下的线程 可以看到TID 线程775占用了96%且持有了很长时间 其实到这一步基本上能猜测到应该是 肯定是那段代码发生了死循环

  3. 线程ID转换为16进制格式

    1
    2
    $ printf "%x\n" 775
    307
  4. 查看java的堆栈信息,打印30行jstack -l pid号 |grep 0x线程号 -A 30

    1
    jstack -l 733 |grep 307 -A 30

Memory占用高的问题

排查步骤

  1. top 按M调整为内存排序

  2. free -m

    • total:总计物理内存的大小。
    • used:已使用多大。
    • free:可用有多少。
    • Shared:多个进程共享的内存总额。
    • Buffers/cached:磁盘缓存的大小。
    • #所以空闲内存=free+buffers+cached=total-used
  3.  cat /proc/meminfo输出各项说明:

    MemTotal: 所有可用RAM大小 (即物理内存减去一些预留位和内核的二进制代码大小)

    MemFree: LowFree与HighFree的总和,被系统留着未使用的内存

    Buffers: 用来给文件做缓冲大小

    Cached: 被高速缓冲存储器(cache memory)用的内存的大小(等于diskcache minus SwapCache ).

    SwapCached:被高速缓冲存储器(cache memory)用的交换空间的大小。已经被交换出来的内存,但仍然被存放在swapfile中。用来在需要的时候很快的被替换而不需要再次打开I/O端口。

    Active: 在活跃使用中的缓冲或高速缓冲存储器页面文件的大小,除非非常必要否则不会被移作他用.

    Inactive: 在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可能被用于其他途径.

    HighTotal: -

    HighFree: 该区域不是直接映射到内核空间。内核必须使用不同的手法使用该段内存。

    LowTotal: -

    LowFree: 低位可以达到高位内存一样的作用,而且它还能够被内核用来记录一些自己的数据结构。

    SwapTotal: 交换空间的总大小

    SwapFree: 未被使用交换空间的大小

    Dirty: 等待被写回到磁盘的内存大小。

    Writeback: 正在被写回到磁盘的内存大小。

    AnonPages:未映射页的内存大小

    Mapped: 设备和文件等映射的大小。

    Slab: 内核数据结构缓存的大小,可以减少申请和释放内存带来的消耗。

    SReclaimable:可收回Slab的大小

    SUnreclaim:不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)

    PageTables:管理内存分页页面的索引表的大小。

    NFS_Unstable:不稳定页表的大小

    VmallocTotal: 可以vmalloc虚拟内存大小

    VmallocUsed: 已经被使用的虚拟内存大小。

    VmallocChunk: largest contigious block ofvmalloc area which is free

    • 执行cat /proc/meminfo |grep -i shmem命令查看共享内存。

    • 标准的 4KB 大小的页面外,内存大页管理内存中的巨大的页面,处理较少的页面映射表,从而减少访问/维护它们的开销。执行cat /proc/meminfo | grep -iE "HugePages_Total|Hugepagesize"查看内存大页。

  4. 通过命令top -Hp PID就可以列出该进程下的所有线程id。按M查看内存占用最高的

  5. 转换成16进制后,jstack -l PID |grep TID -A 30

top命令

top命令选项

-b:以批处理模式操作;
-c:显示完整的治命令;
-d:屏幕刷新间隔时间;
-I:忽略失效过程;
-s:保密模式;
-S:累积模式;
-i<时间>:设置间隔时间;
-u<用户名>:指定用户名;
-p<进程号>:指定进程;
-n<次数>:循环显示的次数。

top命令交互

基础操作

1:显示CPU详细信息,每核显示一行
d / s :修改刷新频率,单位为秒
h:可显示帮助界面
n:指定进程列表显示行数,默认为满屏行数
q:退出top

面板隐藏显示

l:隐藏/显示第1行负载信息;
t:隐藏/显示第23行CPU信息;
m:隐藏/显示第4
5行内存信息;

使用如下按键,进程列表排序

M:根据驻留内存大小进行排序;
P:根据CPU使用百分比大小进行排序;
T:按照 CPU 的累积运算时间排序,也就是按照 TIME+ 项排序;

top命令的输出

top 命令的输出内容是动态的,默认每隔 3 秒刷新一次。命令的输出主要分为两部分:

  1. 第一部分是前五行,显示的是整个系统的资源使用状况,我们就是通过这些输出来判断服务器的资源使用状态的;
  2. 第二部分从第六行开始,显示的是系统中进程的信息;

第一行为任务队列信息,具体内容如下。

内 容 说 明
12:26:46 系统当前时间
up 1 day, 13:32 系统的运行时间.本机己经运行 1 天 13 小时 32 分钟
2 users 当前登录了两个用户
load average: 0.00,0.00,0.00 系统在之前 1 分钟、5 分钟、15 分钟的平均负载。如果 CPU 是单核的,则这个数值超过 1 就是高负载:如果 CPU 是四核的,则这个数值超过 4 就是高负载 (这个平均负载完全是依据个人经验来进行判断的,一般认为不应该超过服务器 CPU 的核数)

第二行为进程信息,具体内容如下。

内 容 说 明
Tasks: 95 total 系统中的进程总数
1 running 正在运行的进程数
94 sleeping 睡眠的进程数
0 stopped 正在停止的进程数
0 zombie 僵尸进程数。如果不是 0,则需要手工检查僵尸进程

第三行为 CPU 信息,具体内容如下

内 容 说 明
Cpu(s): 0.1 %us 用户模式占用的 CPU 百分比
0.1%sy 系统模式占用的 CPU 百分比
0.0%ni 改变过优先级的用户进程占用的 CPU 百分比
99.7%id 空闲 CPU 占用的 CPU 百分比
0.1%wa 等待输入/输出的进程占用的 CPU 百分比
0.0%hi 硬中断请求服务占用的 CPU 百分比
0.1%si 软中断请求服务占用的 CPU 百分比
0.0%st st(steal time)意为虚拟时间百分比,就是当有虚拟机时,虚拟 CPU 等待实际 CPU 的时间百分比

第四行为物理内存信息,具体内容如下

内 容 说 明
Mem: 625344k total 物理内存的总量,单位为KB
571504k used 己经使用的物理内存数量
53840k&ee 空闲的物理内存数量。我们使用的是虚拟机,共分配了 628MB内存,所以只有53MB的空闲内存
65800k buffers 作为缓冲的内存数量

第五行为交换分区(swap)信息,如表

内 容 说 明
Swap: 524280k total 交换分区(虚拟内存)的总大小
Ok used 已经使用的交换分区的大小
524280k free 空闲交换分区的大小
409280k cached 作为缓存的交换分区的大小

通过 top 命令的第一部分就可以判断服务器的健康状态。如果 1 分钟、5 分钟、15 分钟的平均负载高于 1,则证明系统压力较大。如果 CPU 的使用率过高或空闲率过低,则证明系统压力较大。如果物理内存的空闲内存过小,则也证明系统压力较大。

这时,我们就应该判断是什么进程占用了系统资源。如果是不必要的进程,就应该结束这些进程;如果是必需进程,那么我们该増加服务器资源(比如増加虚拟机内存),或者建立集群服务器。

我们还要解释一下缓冲(buffer)和缓存(cache)的区别:

  • 缓存(cache)是在读取硬盘中的数据时,把最常用的数据保存在内存的缓存区中,再次读取该数据时,就不去硬盘中读取了,而在缓存中读取。
  • 缓冲(buffer)是在向硬盘写入数据时,先把数据放入缓冲区,然后再一起向硬盘写入,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。

简单来说,缓存(cache)是用来加速数据从硬盘中”读取”的,而缓冲(buffer)是用来加速数据”写入”硬盘的。

再来看 top 命令的第二部分输出,主要是系统进程信息,各个字段的含义如下:

  • PID:进程的 ID。
  • USER:该进程所属的用户。
  • PR:优先级,数值越小优先级越高。
  • NI:优先级,数值越小、优先级越高。
  • VIRT:该进程使用的虚拟内存的大小,单位为 KB。
  • RES:该进程使用的物理内存的大小,单位为 KB。
  • SHR:共享内存大小,单位为 KB。
  • S:进程状态。
  • %CPU:该进程占用 CPU 的百分比。
  • %MEM:该进程占用内存的百分比。
  • TIME+:该进程共占用的 CPU 时间。
  • COMMAND:进程的命令名。