程序出现性能问题的时候,我们怎么去排查呢?我之前一接到告警就先想是不是程序哪里出问题了,其实这样是不对的。应该首先排查运行的操作系统当时的状况是否健康。毕竟程序运行非常受环境影响,比方说网络IO突然变慢了,可能是对方的服务器出现问题,也可能是网卡流量突然增大,导致等待时间过长。比如程序突然卡了,会不会是因为CPU负载增高了。下面我总结了一下,当程序出现性能问题,我们应该从哪些方面来排查呢。
我们先从CPU利用率、系统负载、内存使用情况、磁盘IO、网络IO等方面来了解一下linux的运行环境系统分析。
一. CPU利用率
命令为: cat /proc/stat |grep cpu
结果类似如下:
cpu 179584151 98 68568703 21032948653 45790 5837 6734236 0 0 0
cpu0 10215468 2 3003061 872428513 3152 726 467113 0 0 0
cpu1 7555721 1 3100525 875188647 1668 828 479287 0 0 0
cpu2 7512959 16 3465364 874751170 715 826 523902 0 0 0
cpu3 7328152 9 3652410 876087402 836 0 170879 0 0 0
cpu4 7152786 4 3294056 876698848 638 0 170233 0 0 0
cpu5 6935775 6 3038514 877141786 7839 10 179215 0 0 0
cpu6 8697735 1 3032698 875377195 4212 0 178054 0 0 0
......
根据机器配置,可能有多个CPU。第一行的数值表示的是CPU总的使用情况,其他各行是多核机器中每个具体CPU的参数。
我们分别看看上面各列参数的含义:
1.user:从系统启动开始累计到当前时刻,用户态的CPU时间 ,不包含 nice值为负的进程。
2.nice:从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间
3.system:从系统启动开始累计到当前时刻,内核态时间
4.idle:从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间
5.iowait:从系统启动开始累计到当前时刻,硬盘IO等待时间
6.irq:从系统启动开始累计到当前时刻,硬中断时间
7.softirq:从系统启动开始累计到当前时刻,软中断时间
8.steal:在虚拟环境下 CPU 花在处理其他作业系统的时间,Linux 2.6.11 开始才开始支持。
9.guest:在 Linux 内核控制下 CPU 为 guest 作业系统运行虚拟 CPU 的时间,Linux 2.6.24 开始才开始支持。
这里先解释一下什么是nice值:
系统中运行的每个进程都有一个优先级(亦称“nice 值”),其范围从 -20 (最高优先级)到 19 (最低优先级)。
默认情况下,进程的优先级是 0 (“基本”调度优先级)。优先级比较大的进程(nice 值比较小,最低到 -20)相对优先级比较小的进程(直到 19)
将比较频繁地被调度运行,因此就拥有更多的进程周期。一般用户只能降低它们自己进程的优先级别,并限于 0 到 19 之间。
超级用户(root)可以将任何进程的优先级设定为任何值。
我们看看CPU利用率是怎么计算的:
cpu_total=user+nice+system+idle+iowait+irq+softirq =》总时间cpu_used=user+nice+system+irq+softirq=》使用时间
根据这两个值在不同世间点上的采集结果求差值再除以时间间隔,就可以得到一个时间段内的cpu使用率。可见总的时间就是使用时间加上硬盘IO的时间以及CPU空闲时间。
其他相关的命令:
cat /proc/cpuinfo
cat /proc/pid(此处要填写进程id)/stat
二. CPU负载
三. 系统内存
命令为:free -m
total used free shared buffers cached
Mem: 3320 3185 134 0 43 2557
-/+ buffers/cache: 584 2735
Swap: 2055 2055 0
其他相关命令:
cat /proc/(进程ID)/smaps
四. 磁盘IO
命令为:iostat -x 10
结果类似如下:
Linux XXXXXXXXXXXXX 01/10/17 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.82 0.00 0.53 0.63 0.00 98.02
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
vda 0.05 4.76 0.07 2.06 2.45 54.57 26.78 0.09 42.35 2.88 0.61
vdb 0.00 9.11 0.25 6.02 6.56 121.11 20.37 0.10 15.63 3.06 1.92
另一台机器上:
sda 0.01 2.13 0.01 2.36 0.17 169.20 143.33 0.00 1.83 3.59 1.83 0.07 0.02
首先能看到avg-cpu这一行,前三列分别是用户态,nice值,内核态所占时间比。然后是硬盘io等待的时间,其他时间以及空闲时间。
每一列的含义如下:
rrqm/s: 每秒进行merge的读操作数目。
wrqm/s: 每秒进行merge的写操作数目。
r/s: 每秒完成的读 I/O 设备次数。
w/s: 每秒完成的写 I/O 设备次数。
rkB/s: 每秒读K字节数。是 rsect/s 的一半,因为扇区大小为512字节
wkB/s: 每秒写K字节数。是 wsect/s 的一半
rsec/s: 每秒读扇区数。(这个和上面的rkB/s其实是可以相互计算的)
wsec/s: 每秒写扇区数。(这个和上面的wkB/s其实是可以相互计算的)
avgrq-sz: 平均每次设备I/O操作的数据大小 (扇区)
avgqu-sz: 平均I/O队列长度。
await: 平均每次设备I/O操作的等待时间 (毫秒)
svctm: 平均每次设备I/O操作的服务时间 (毫秒)
%util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。
根据这些参数我们可以理解当前IO的性能状况:1)如果%util 接近100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈
2) svctm的大小一般和磁盘性能有关,CPU/内存的负荷也会对其有影响,请求过多也会间接导致 svctm 的增加。
3)await的大小一般取决于服务时间(svctm) 以及 I/O 队列的长度和 I/O 请求的发出模式。一般来说svctm < await,因为同时等待的请求的等待时间被重复计算了。如果svctm 比较接近await,说明I/O 几乎没有等待时间
4)如果await 远大于svctm,说明I/O队列太长,应用得到的响应时间变慢
5)队列长度(avgqu-sz)也可作为衡量系统 I/O 负荷的指标,但由于 avgqu-sz 是按照单位时间的平均值,所以不能反映瞬间的 I/O 洪水。
6)如果响应时间超过了用户可以容许的范围,这时可以考虑更换更快的磁盘,调整内核elevator算法,优化应用,或者升级 CPU。
7)如果%util很大,而rkB/s和wkB/s很小,一般是因为磁盘存在较多的磁盘随机读写,最好把磁盘随机读写优化成顺序读写。
五. 网络IO
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
eth0: 1617072305 26950894 0 26950821 0 0 0 20 20132 85 0 0 0 0 0 0
eth1: 105406227830901 73602963634 0 1 1685 0 0 02556488698778 25535054407 0 0 0 0 0 0
bond0: 105407844903272 73629914529 0 26950822 1685 0 0 20 2556488718910 25535054492 0 0 0 0 0 0
lo: 301581754 1155867 0 0 0 0 0 0 301581754 1155867 0 0 0 0 0 0
网络IO中还有一个就是连接数,鉴于目前TCP是主流,我们只看系统的TCP连接数。
命令为:cat /proc/net/snmp
Ip: 2 64 5677934 0 0 0 0 0 4167838 4633344 0 10 0 0 0 0 0 0 0
Icmp: InMsgs InErrors InCsumErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
Icmp: 116424 33808 0 116401 0 0 0 12 11 0 0 0 0 0 50742 0 50731 0 0 0 0 0 11 0 0 0 0
IcmpMsg: InType3 InType5 InType8 OutType0 OutType3
IcmpMsg: 116401 12 11 11 50731
Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResetsCurrEstab InSegs OutSegs RetransSegs InErrs OutRsts InCsumErrors
Tcp: 1 200 120000 -1 190217 1883 25602 1763 3 2821900 3894685 557672 2 11325 0
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors
Udp: 262 19 0 587723 0 0 0
UdpLite: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors
UdpLite: 0 0 0 0 0 0 0