我们通常都会习惯性的用top 去查看进程cpu 使用率,但是通常会进入以下误区
系统cpu idle很高cpu不是性能瓶颈
通常我们在看进程cpu使用率的时候用的是top,默认是按照cpu使用排序的,而且这时候看到的进程cpu使用情况是整个进程的,进程内部所有线程cpu使用的总和,这时候如果要进一步确定cpu不是性能瓶颈就要进一步查看进程内每个线程cpu使用情况:
top -h -p pid
这时候会将进程内所有线程按照cpu使用情况排序列出来,这时候观察cpu使用情况,这时候如果有进程cpu使用率持续在90% 或者100% 说明cpu就有可能是瓶颈了。
比如说一个web服务器在设计的时候由一个进程专门进行accept 新的连接,连接完成后交由其他进程处理,此时如果该进程用满单核cpu就会造成性能瓶颈。这时候可以进一步确认将cpu 用满的进程在干啥,是否在进行符合我们预期的操作:
pstack pid
案例
在nginx multi_accept on; 这一项打开后,在压力极大的情况下,每一秒有3w+的tcp连接请求过来nginx 某个worker 每时每刻都会有新的连接需要建立,导致这个worker 一直hold 住accept互斥锁不释放, 造成nginx 严重负载不均,这个worker 一直在accept 新的连接被打满(满占一个cpu),而其他worker闲着没事做, multi_accept 项关闭后解决。 pstack 看这个worker 一直在accept 新的连接。
系统上每时每刻都会有很多软中断产生,这些软中断会悄无声息的使用cpu,而通常由硬件产生的软中断对cpu具有亲和性,比如说中断号为100的中断对cpu0 有亲和性,如果某个时候100 号软中断非常多就会造成cpu0被打满,处理不了更多中断造成性能瓶颈。这时候可以用以下命令查看下单个cpu的使用率:
top +1 (输入top命令后按1)有可能cpu核心太多屏幕太小显示不出来,尝试用下面命令
mpstat -p all 1
具体案例下面的网络部分。
a、系统cpu idle 很高cpu不一定不是性能瓶颈,有可能单个进程吃满单核cpu
b、系统cpu idle 很高也没发现有单个进程吃满单核cpu情况下cpu不一定不是瓶颈,有可能单核cpu被打满,因cpu亲和性问题造成性能瓶颈
注:当然还有很多其他情况会使用cpu,比如说进程切换等
通常查看网络状况的时候都是看机器网卡是否被打满,我通常用的是ifstat 或者dstat 来看, 但是也会有以下误区
网卡未打满网络就不是瓶颈
这种情况比较好理解,假设用http 短连接上传到oss数据,每个object 1字节,从抓包上看一次put 操作要产生八个包tcp 三次握手,四次挥手加上一次1字节数据传输,光进行这一个字节数据的传输就要产生8个tcp 报文,底层网卡怎么滴也会产生8次中断吧。不过这种场景只有在很极端的情况下才会出现,而且通常都是后端server 先到达性能瓶颈。
这种情况也比较好理解,因为现在基本上网络通信用的都是tcp,如果上游网络环境差会造成丢包现象出现,丢包会触发tcp协议的拥塞控制算法,进而导致整体网络使用率上不去,这里可以使用tsar 工具查看系统丢包率 tsar --live, 注意观察retran 一项。但有时候系统丢包率高有可能并不是上游网络环境差造成,具体见2.3 分析。
这种情况比较常见,尤其是在万兆网的机器上,网络流量达到1gb 也算是比较轻松的事情,但是经常会有这种情况出现,万兆网机器,网络流量打到400m的时候就再也打不上去了,利用淘宝对外提供的开源监控工具tsar 查看下系统丢包率,如果有异常有可能是2.2 描述的原因,但是也有可能是自身原因。
分析步骤:
1、查看系统cpu使用情况
注意观察是否出现某个cpu被软中断打满的情况,如下图:

如果出现如下情况说明是网卡软中断对cpu0有亲和性,需要对网卡软中断进行分流了。
网卡打满单核cpu情况造成的影响很多很坏而且不好查,首先我们知道网卡一定是有自己的buffer的,如果网卡产生的软中断没有被及时处理,就会导致网卡buffer溢出,直接导致的后果就是丢包,丢包会触发tcp拥塞控制导致网卡使用率上不去。
当前一般千兆网或者万兆网都是多队列网卡,网卡产生的软中断会对于到多个中断号,查看多队列网卡对应的中断号:
cat /proc/interrupts | grep eth | awk '{print $1 " " $nf}'
vim 打开 /proc/interrupts 查看软中断是否都落在同一个cpu上
更精确的查看方法是看 /proc/irq/$interupt_id/smp_affinity, 里面会有一串十六进制数字
a、丢包严重不一定是上游网络问题
b、网卡util不高不一定不是性能瓶颈
关于磁盘通常都是用iostat 去看磁盘使用情况,但是也有问题,也会进入误区
通常我们在查看磁盘使用率的时候都会用iostat 去看,我比较常用的是如下命令:
iostat -x 1
最后一项有个磁盘util 项,千万不要被这个值迷惑,这个值只是磁盘在1s 内的平均使用率
有可能在1s内的某个瞬间磁盘使用率达到100% 到达性能瓶颈。
在机器压力比较大的时候发现nginx 和我们的后端server 都有不同程度的丢日志现象,nginx 日志和我们后端server日志都是打在同一块盘上的,于是开始怀疑是磁盘iops被打满导致,想当然的用iostat -x 1 查看磁盘使用率,看到这块盘在1s 内有util 可以达到80%,但是没有看到100%的情况,因此开始怀疑有可能在1s 内磁盘使用率达到100%,为了证实我的想法将nginx 日志和后端server 日志分别达到不同磁盘上,再用iostat 去观察,发现两块盘都有使用率到80%的情况,加起来超过100%,因此确定打在一块盘上确实是会造成iops争抢导致丢日志。
a、一段时间内磁盘使用率低不代表瞬时使用率也低
关于了内存这块,测试过程中很少出现因内存问题造成性能瓶颈,所以没太多经验,不过还是有一点需要强调下
是否是内存free 的越少表面内存就越不够用?不是这样的,free 内存越少只能证明linux 对内存使用率越高,通常系统可用内存分为三块,一块是free 部分,一块是读cache 部分,还有写buffer,cache通常指的是读cache(linux 会利用多余的主存来做读cache,也就是传说中的page cache)。
可以看到下一行-/+ buffers/cache,我理解这里的free 才是真正的使用可用内存,当free 量不够之后系统清先清cache 和 buffer 使用的内存供进程使用,等这些都用完了才会考虑swap。
a、free 内存少不代表系统内存不够用
使用到的命令