CPU

一块CPU芯片可能包含多个物理核,每个物理核都是一个实打实的运算核心,包括运算器、存储器等。
超线程技术可以让一个物理核在单位时间内同时处理两个线程,变成两个逻辑和。但它并不会拥有传统单核2倍的处理能力,也无法提供完整的并行处理能力。
举个栗子,假设一个CPU芯片是一个班级,两个物理核也就是两个同学,每个同学分别担任两种班干部,那么一种班干部就是一种逻辑核。但是,这个班级只有两个同学,也就是两个物理核,虽然他们掌握着四个人的工作,但是并不能把他们真的当成四个人。

  1. [@]# cat /proc/cpuinfo
  2. // 查看CPU信息
  3. [@]# cat /proc/cpuinfo | grep 'physical id' | sort | uniq | wc -l
  4. // 查看CPU个数
  5. [@]# cat /proc/cpuinfo | grep 'cpu cores' | sort | uniq
  6. // 查看CPU物理核数
  7. [@]# cat /proc/cpuinfo | grep 'siblings' | sort | uniq
  8. // 查看CPU逻辑核数

CPU使用率

CPU使用率就是CPU非空闲态运行的时间占比,它反映了CPU的繁忙程度。
比如,单核CPU1s内非空闲态运行时间为0.8s,那么它的CPU使用率就是80%;双核CPU1s内非空闲态运行时间分别为0.4s和0.6s,那么,总体CPU使用率就是 (0.4s+0.6s)/(1s*2)=50%,其中2表示CPU核数,多核CPU同理。
在Linux系统下,top命令可查看CPU使用情况:
image.png
us(user)用户空间占比;
sy(sys)内核空间占比;
ni(nice)修正优先级的进程占比;
id(idle)空闲空间占比;
wa(iowait)I/O时间占比;
hi(hardirq)硬件中断时间
si(softirq)软件中断时间
st(steal)实时、虚拟机占用
需要注意的有,us值越高,表示有用户态应用比较繁忙,如数据库、Web服务;sywa值越高,表示系统存在瓶颈,其中wa可以通过iostat命令进一步分析。

平均负载

平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。
可运行状态进程包括正在使用CPU或等待使用CPU的进程;
不可中断状态进程是指处于内核态关键流程中的进程,且该流程不可被打断,它本质上是系统对进程和硬件设备的一种保护机制。
在Linux系统下,top命令可查看平均负载:
image.png
三个数字分别代表1分钟、5分钟、15分钟内系统的平均负载,该值越小,表示系统工作量越少,负荷越低;反之负荷越高。
平均负载和CPU使用率的区别在于,平均负载不仅包括正在使用CPU的进程,还包括等待CPU和I/O的进程,因此两者不能等同。
如CPU密集型应用,大量进程等待或使用CPU,此时CPU使用率和平均负载呈正相关状态;
而I/O密集型应用,大量进程等待I/O,此时平均负载会升高,但CPU使用率不一定很高。
理想状态下,每个CPU都应该满负荷工作,且没有等待进程,但在实际生产中,通常当平均负载高于CPU逻辑核数量的70%左右,就要开始防止系统恶化;而当平均负载高于CPU逻辑核数量,就要寻找解决办法,降低平均负载。

CPU实用命令汇总

CPU占用最多的前10个进程

ps auxw | head -1;ps auxw | sort -rn -k3 | head -10

内存消耗最多的前10个进程

ps auxw | head -1;ps auxw | sort -rn -k4 | head -10

虚拟内存占用最多的前10个进程

ps auxw | head -1;ps auxw | sort -rn -k5 | head -10

Dstat命令查看全局

Dstat命令是一个可以取代vmstatiostatnetstatifstat的集成产品,使用时需要安装相关软件包。
dstat
该命令默认显示信息就包含CPU状态、磁盘统计、网络统计、分页统计以及系统统计。
dstat -glms --top-mem
查看全部内存都在被谁占用
dstat -cyl --top-cpu
查看CPU资源损耗统计

CPU优化案例汇总

UsCPU和NiceCPU过高时,说明用户态进程占用了较多CPU,应该重点排查进程的性能问题;
SyCPU过高,说明内核态占用了较多CPU,应该重点排查内核线程或者系统调用的性能问题;
I/OCPU高,说明等待I/O的时间比较长,应该重点排查系统存储是否出现I/O问题;
软硬中断高,说明软硬中断相关的处理程序占用了较多CPU,应该重点排查内核中的中断服务程序。

用户态CPU使用率高

用户态CPU使用率反映了应用程序的繁忙程度,通常与代码息息相关。
1、通过top命令找到CPU消耗最多的进程号;
2、通过top -Hp PID命令(该PID为进程号)找到CPU消耗最多的线程号;
3、通过printf "%x\n" PID命令(该PID为线程号)输出该线程号对应的16进制号码;
4、通过jstack 进程号 | grep 16进制线程号 -A 10命令找到CPU消耗最多的线程方法堆栈,定位可疑代码。
如果是非JAVA应用,可以使用perf软件包命令。

磁盘

磁盘是可以持久化存储的设备,根据存储介质的不同,常见磁盘可以分为两类:机械磁盘和固态磁盘。
机械磁盘主要由盘片和读写磁头组成,数据就存储在盘片的环状磁道中。如果I/O请求刚好连续,那就不需要磁道寻址,自然可以获得最佳性能。但如果是随机I/O,它就需要不停地移动磁头,来定位数据位置,导致读写速度就会比较慢。
固态磁盘通常缩写为 SSD,由固态电子元器件组成。固态磁盘不需要磁道寻址,所以,不管是连续I/O,还是随机I/O 的性能,都比机械磁盘要好得多。

磁盘架构

最简单的,就是直接作为独立磁盘设备来使用。这些磁盘,往往还会根据需要,划分为不同的逻辑分区,每个分区再用数字编号。比如/dev/sda 可以分成两个分区/dev/sda1/dev/sda2
另一个比较常用的架构,是把多块磁盘组合成一个逻辑磁盘,构成冗余独立磁盘阵列,也就是RAID,从而可以提高数据访问的性能,并且增强数据存储的可靠性。
根据容量、性能和可靠性需求的不同,RAID一般可以划分为多个级别,如RAID0、RAID1、RAID5、RAID10等。
最后一种架构,是把这些磁盘组合成一个网络存储集群,再通过NFS、SMB、iSCSI等网络存储协议,暴露给服务器使用。
其实在 Linux 中,磁盘实际上是作为一个块设备来管理的,也就是以块为单位读写数据,并且支持随机读写。每个块设备都会被赋予两个设备号,分别是主、次设备号。主设备号用在驱动程序中,用来区分设备类型;而次设备号则是用来给多个同类设备编号。

通用块层

为了减小不同块设备的差异带来的影响,在文件系统和磁盘驱动中间,存在一个块设备抽象层,它是磁盘I/O的核心,功能主要有两点。
第一,与虚拟文件系统功能类似。向上,为文件系统和应用程序,提供访问块设备的标准接口;向下,把各种异构的磁盘设备抽象为统一的块设备,并提供统一框架来管理这些设备的驱动程序。
第二个功能,通用块层还会给文件系统和应用程序发来的 I/O 请求排队,并通过重新排序、请求合并等方式,提高磁盘读写的效率。也就是I/O调度。

I/O栈

Linux 存储系统的I/O栈,由上到下可以分为三个层次,分别是文件系统层、通用块层和设备层。
文件系统层,包括虚拟文件系统和其他各种文件系统的具体实现。它为上层的应用程序,提供标准的文件访问接口;对下会通过通用块层,来存储和管理磁盘数据。
通用块层,包括块设备I/O队列和I/O调度器。它会对文件系统的I/O请求进行排队,再通过重新排序和请求合并,然后才要发送给下一级的设备层。
设备层,包括存储设备和相应的驱动程序,负责最终物理设备的I/O操作。
存储系统的I/O,通常是整个系统中最慢的一环。所以,Linux通过多种缓存机制来优化I/O效率。
例如,为了优化文件访问的性能,会使用页缓存、索引节点缓存、目录项缓存等多种缓存机制,以减少对下层块设备的直接调用。
同样,为了优化块设备的访问效率,会使用缓冲区,来缓存块设备的数据。

磁盘实用命令汇总

Iostat命令查看磁盘状态

这是用于查看磁盘情况的一个很棒的工具,无论是对工作负载还是性能表现来说。
iostat -xz 1
该命令输出列详情,包括常规的读写次数、读写数量,以及以毫秒级展示I/O平均消耗时间的await;展示向设备发出请求的平均数avgqu-sz;和展示设备利用率的%util
如果该存储设备是一个面向很多后端磁盘的逻辑磁盘设备,则100%利用率可能只是意味着当前正在处理某些I/O占用,然而,后端磁盘可能远未饱和,并且可能能够处理更多的工作。
所以,磁盘I/O性能较差不一定是程序的问题。许多技术通常是异步I/O,使应用程序不会被阻塞并遭受延迟(例如,预读,以及写缓冲)。

磁盘优化案例汇总

磁盘空间释放问题

问题描述:
分区高占用率,rm删除大文件后未释放资源。
原因排查:
在Linux系统中,通过rm或者文件管理器删除文件,只是将它从文件系统的目录结构上解除链接unlink;如果文件在删除时是被打开的,那么进程将仍然可以读取该文件,也就是说并没有改变文件正在读取的状态,所以磁盘空间也就会一直被占用。
解决办法:
1、df -lh查看磁盘使用状况
2、找到被删文件所在分区,如/data分区
3、查看被删除的所有文件
lsof -n /data | grep deleted
4、杀死这些文件的delete进程
lsof -n /data | grep deleted | awk '{print $2}' | xargs kill -9
5、随着进程被杀死,资源逐渐释放,再次检查就正常了
lsof -n /data | grep delete

文件系统挂载I/O优化

默认情况下,Linux文件系统在文件被操作时会记录下文件的一些时间戳。
如记录文件访问时间的atime,记录文件内容修改时间的mtime,以及记录文件状态修改时间的ctime
因为系统运行时要访问大量文件,如果能减少一些动作,将会显著提高磁盘I/O的效率、提升文件系统的性能。
可以通过在文件系统挂载时加上noatime参数来大幅提高文件系统性能。

  1. [@]#vim /etc/fstab
  2. UUID=5f543816-8bcb-477a-a356-341b62df19d0 / ext4 defaults,noatime 0 1
  3. [@]#mount -o remount /
  4. //修改设置后需要重新加载挂载规则
  5. [@]#mount | grep noatime
  6. /dev/sda2 on / type ext4 (rw,noatime)
  7. /dev/sda5 on /data type ext4 (rw,noatime)
  8. /dev/sda3 on /home type ext4 (rw,noatime)

内存

我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念。
物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在Linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间Swap。
作为物理内存的扩展,linux会在物理内存不足时,使用交换分区的虚拟内存,更详细的说,就是内核会将暂时不用的内存块信息写到交换空间,这样以来,物理内存得到了释放,这块内存就可以用于其它目的,当需要用到原始的内容时,这些信息会被重新从交换空间读入物理内存。

Linux内存机制

Linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。
而这种页面交换操作,会不时进行,以保持尽可能多的空闲物理内存。即使并没有什么事情需要内存,Linux也会交换出暂时不用的内存页面。这可以避免等待交换所需的时间。
另外,在Linux中,当应用程序需要读取文件中的数据时,操作系统先分配一些内存,将数据从磁盘读入到这些内存中,然后再将数据分发给应用程序;反之,当需要往文件中写数据时,操作系统先分配内存接收用户数据,然后再将数据从内存写到磁盘上。为避免因大量数据频繁消耗内存导致性能下降,Linux引入了bufferscached这两种缓冲机制。
bufferscached都是内存操作,但是两者缓冲的内容确是不一样的。**buffers**用来缓冲块设备,它只记录文件系统的元数据以及交换页面跟踪;而**cached**是用来给文件做缓冲。通俗一点讲,**buffers**主要用来记录目录下内容的属性及权限等等。而**cached**则直接用来记忆打开过的文件和程序。

Swap交换空间(虚拟内存)

一般情况下,当内存小于4Gb时,Swap分区设置建议是内存的两倍;而内存大于4Gb时,Swap只要比内存大就行。
cat /proc/sys/vm/swappiness
该命令可以查看虚拟内存使用规则,如值为40,就表示物理内存使用60%后会使用Swap。
值越大表示越倾向于使用Swap,可以设定为0,这样并不会禁用Swap,只是降低使用Swap的可能性。
如果要修改该值,可以使用下面的方法:

  1. // 临时修改swappiness值
  2. [@]# sysctl vm.swappiness=10
  3. // 永久修改swappiness值
  4. [@]# vim /etc/sysctl.conf
  5. /* 加入参数:
  6. vm.swappiness = 35 */
  7. [@]# sysctl -p /etc/sysctl.conf
  8. [@]# cat /proc/sys/vm/swappiness
  9. // 重新加载文件,查看是否生效

内存实用命令汇总

释放内存

修改配置文件/proc/sys/vm/drop_caches手动释放内存。该文件记录了缓存释放规则的参数,参数值为0~3之间任意数字。
0不释放缓存;
1释放页缓存;
2释放dentriesinodes缓存;
3释放所有缓存;
可以直接往文件中写入3来释放所有缓存。
echo "3" > /proc/sys/vm/drop_caches

释放Swap

一般可以通过重新挂载Swap分区来释放Swap。
根据内存机制,Swap分区一旦释放,所有存放在Swap分区的文件都会转存到物理内存上。所以,首先要保证内存剩余要大于等于Swap使用量,否则会宕机!
具体步骤如下:
1、查看当前Swap分区挂载路径
2、关停这个分区
3、检查状态
4、将Swap重新挂载到原位置
5、查看挂载是否成功
image.png

进程

进程状态类别

进程的状态,可以在top命令中的S列观察,主要有R、D、Z、S、I几种状态。
R表示正在运行或等待运行的进程;
D表示进程正在与硬件交互,且不允许被其他进程中断;
Z表示僵尸进程,也就是进程实际上已经结束了,但是父进程还未回收它的资源;
S表示可中断进程,即睡眠状态,重新唤醒时进入R状态;
I表示空闲状态,主要分配在不可中断进程的内核线程上。它与D状态的区别是,D状态会导致平均负载升高,而I状态则不会。
不可中断状态的进程,一般会在很短时间内结束,但如果系统或者硬件发生故障,进程可能会在不可中断状态保持很久,这时就需要注意下,系统是不是出现了I/O等性能问题。
僵尸进程,这是多进程应用很容易碰到的问题。正常情况下,当一个进程创建子进程后,它应该通过系统调用wait等待子进程结束,回收子进程资源。而子进程结束时,也会向它的父进程发送SIGCHLD信号,异步回收资源。
通常情况下,僵尸进程持续的时间也都比较短,在父进程回收它的资源后消亡。或者在父进程退出后,由init进程回收消亡。
但一旦父进程没有及时处理子进程的终止,使其还一直保持在运行状态,那么子进程就会一直处于僵尸状态。大量的僵尸进程会用尽PID进程号,导致新进程无法创建,所以这种情况一定要避免。

进程实用命令汇总

Pidstat分析进程状态

Pidstat是sysstat软件套件的一部分,sysstat包含很多监控Linux系统状态的工具。

  1. [@]# yum -y install sysstat
  2. // 安装sysstat工具包
  3. [@]# pidstat
  4. // 默认后缀-p参数,只显示正在活动的任务
  5. [@]# pidstat -d -p PID
  6. // 使用-d参数获取I/O的统计数据
  7. # 参数:
  8. /*-u 默认的参数,显示各个进程的cpu使用统计
  9. -r 显示各个进程的内存使用统计
  10. -d 显示各个进程的IO使用情况
  11. -p 指定进程号
  12. -w 显示每个进程的上下文切换情况
  13. -t 显示选择任务的线程的统计信息外的额外信息
  14. -T { TASK | CHILD | ALL }
  15. 这个选项指定了pidstat监控的。TASK表示报告独立的task,CHILD关键字表示报告进程下所有线程统计信息。ALL表示报告独立的task和task下面的所有线程。
  16. 注意:task和子线程的全局的统计信息和pidstat选项无关。这些统计信息不会对应到当前的统计间隔,这些统计信息只有在子线程kill或者完成的时候才会被收集。
  17. -V 版本号
  18. -h 在一行上显示了所有活动,这样其他程序可以容易解析。
  19. -I 在SMP环境,表示任务的CPU使用率/内核数量
  20. -l 显示命令名和所有参数*/
  21. # 示例:
  22. [@]# pidstat -r 2 5
  23. // 获取5次统计数据结果,间隔2秒
  24. [@]# pidstat -T CHILD -C mysql
  25. // 显示所有mysql子进程
  26. [@]# pidstat -urd -h
  27. // 将所有统计数据导出到文本

僵尸进程清除方法

  1. ps -ef | grep defunct | grep -v grep | wc -l
  2. // 查看僵尸进程

1、改写父进程

在子进程死后要为它收尸。具体做法是接管SIGCHLD信号。子进程死后,会发送SIGCHLD信号给父进程,父进程收到此信号后,执行waitpid()函数为子进程收尸。这是基于这样的原理:就算父进程没有调用wait,内核也会向它发送SIGCHLD消息,尽管对的默认处理是忽略,如果想响应这个消息,可以设置一个处理函数。

2、Kill -18 PPID

这个信号是告诉父进程,该子进程已经死亡,请回收分配给它的资源。

3、终止父进程

如果方法2不能终止,可采用终止其父进程的方法。先看其父进程有无其他子进程,如果有,可能需要先kill掉其他子进程PID1、PID2等等。
kill –15 PID1 PID2 && kill -15 PPID
image.png

网络

网络实用命令汇总

Sar命令

sar -n DEV 1
该命令的rxkB/stxkB/s列可以用来检查网络接口的吞吐量,以及是否达到限额。
sar -n TCP,ETCP 1
该命令的active/spassive/s,以及retrans/s列,分别表示本地和远程每秒发起的TCP连接数,以及TCP重传次数。