Linux性能优化实战笔记

02 | 基础篇:到底应该怎么理解“平均负载”? 

当平均负载高于cpu数量70%的时候,就应该分析排查负载高的问题。

watch -d uptime 查看cpu负载变化的命令

grep 'model name' /proc/cpuinfo | wc -l 查看系统cpu个数

stress是一个linux系统压力测试工具

stress --cpu 1 --timeout 600 模拟一个cpu使用率100%的场景

stress -i 1 --timeout 600 模拟I/O压力,即不停地执行sync

stress -c 8 --timeout 600 模拟8个进程,当运行进程超出cpu运行能力时,就会出现等待cpu的进程

 

mpstat -P ALL 5 查看cpu使用率的变化情况,每隔5秒输出一组数据

pidstat -u 5 1 间隔5秒输出一组数据,查看哪个进程导致cpu使用率100%

 

CPU使用率是单位时间内CPU繁忙的情况的统计,跟平均负载并不一定完全对应。

  • CPU密集型进程,使用大量CPU会导致平均负载升高,此时这两者是一致的。
  • I/O密集型进程,等待I/O也会导致平均负载升高,但CPU使用率不一定很高。
  • 大量等待CPU的进程调度也会导致平均负载升高,此时CPU使用率也会比较高。

 

03 | 基础篇:经常说的 CPU 上下文切换是什么意思?(上)

根据任务的不同,CPU的上下文切换就可以分为几个不同的场景,也就是进程上下文切换、线程上下文切换以及中断上下文切换。

一次系统调用的过程,其实是发生两次CPU上下文切换。系统调用过程通常称为特权模式切换,而不是上下文切换。但实际上,系统调用过程中,CPU的上下文切换还是无法避免的。

过多的上下文切换,会把CPU时间消耗在寄存器、内核栈以及虚拟内存等数据的保存与恢复上,从而缩短进程真正运行的时间,导致系统的整体性能大幅下降。

 

04 | 基础篇:经常说的 CPU 上下文切换是什么意思?(下)

# 每隔 5 秒输出 1 组数据
$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 7005360  91564 818900    0    0     0     0   25   33  0  0 100  0  0

cs(context switch)是每秒上下文切换的次数

in(interrupt)是每秒中断的次数

r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待cpu的进程数

b(Blocked)则是处于不可中断睡眠状态的进程数

 

# 每隔 5 秒输出 1 组数据
$ pidstat -w 5
Linux 4.15.0 (ubuntu)  09/23/18  _x86_64_  (2 CPU)

08:18:26      UID       PID   cswch/s nvcswch/s  Command
08:18:31        0         1      0.20      0.00  systemd
08:18:31        0         8      5.40      0.00  rcu_sched

cswch(voluntary context switches)每秒自愿上下文切换的次数,nvcswch是非自愿

自愿上下文切换:指进程无法获取所需资源,导致的上下文切换。如I/O、内存等系统资源不足。

非自愿上下文切换:指进程时间片已到等原因,被系统强制调度。如大量进程都在抢CPU时。

 

用sysbench --threads=10 --max-time=300 threads run模拟上下文切换

分析pidstat得出sysbench占用cpu,而pidstat、kworker、sshd的上下文切换多

# 每隔 1 秒输出 1 组数据(需要 Ctrl+C 才结束)
# -w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标
$ pidstat -w -u 1
08:06:33      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
08:06:34        0     10488   30.00  100.00    0.00    0.00  100.00     0  sysbench
08:06:34        0     26326    0.00    1.00    0.00    0.00    1.00     0  kworker/u4:2

08:06:33      UID       PID   cswch/s nvcswch/s  Command
08:06:34        0         8     11.00      0.00  rcu_sched
08:06:34        0        16      1.00      0.00  ksoftirqd/1
08:06:34        0       471      1.00      0.00  hv_balloon
08:06:34        0      1230      1.00      0.00  iscsid
08:06:34        0      4089      1.00      0.00  kworker/1:5
08:06:34        0      4333      1.00      0.00  kworker/0:3
08:06:34        0     10499      1.00    224.00  pidstat
08:06:34        0     26326    236.00      0.00  kworker/u4:2
08:06:34     1000     26784    223.00      0.00  sshd

查看进程对应的线程的上下文切换 

# 每隔 1 秒输出一组数据(需要 Ctrl+C 才结束)
# -wt 参数表示输出线程的上下文切换指标
$ pidstat -wt 1
08:14:05      UID      TGID       TID   cswch/s nvcswch/s  Command
...
08:14:05        0     10551         -      6.00      0.00  sysbench
08:14:05        0         -     10551      6.00      0.00  |__sysbench
08:14:05        0         -     10552  18911.00 103740.00  |__sysbench
08:14:05        0         -     10553  18915.00 100955.00  |__sysbench
08:14:05        0         -     10554  18827.00 103954.00  |__sysbench

查看到中断次数增多的原因 

# -d 参数表示高亮显示变化的区域
$ watch -d cat /proc/interrupts
           CPU0       CPU1
...
RES:    2450431    5279697   Rescheduling interrupts
...

05 | 基础篇:某个应用的CPU使用率居然达到100%,我该怎么办?

压测代码 

ab -c 10 -n 10000 http://10.240.0.5:10000/

 top查看cpu占用率高的程序

perf top进上步查看调用关系

# -g 开启调用关系分析,-p 指定 php-fpm 的进程号 21515
$ perf top -g -p 21515

定位到函数

 

06 | 案例篇:系统的 CPU 使用率很高,但为啥却找不到高 CPU 的应用?

# 记录性能事件,等待大约 15 秒后按 Ctrl+C 退出
$ perf record -g

# 查看报告
$ perf report

常规问题无法解释cpu使用率情况时,首先要想到可能短时间应用导致的问题:

1、应用里直接调用了其他二进制程序,这些程序通常运行时间短,通过top工具不易发现

2、应用本身在不停地崩溃重启,而启动过程的资源初始化,很可能会占用相当多的cpu。

 

07 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(上)

 用我们熟悉的ps和top命令可以查看进程状态,这些状态包括运行(R)、空闲(I)、不可中断睡眠(D)、可中断睡眠(S)、僵尸(Z)以及暂停(T)等。

不可中断睡眠:表示进程正在跟硬件交互,为了保护进程数据和硬件的一致性,系统不允许其它进程或中断打断这个进程。进程长时间处于不可中断状态,通常表示系统有I/O性能问题。

僵尸进程表示进程已经退出,但它的父进程还没有回收子进程占用的资源。短暂的僵尸进程状态我们通常不会管理,但进程长时间处于僵尸状态,就应该注意了,可能应用程序没有正常处理子进程的退出。

 

08 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(下)

dstat命令观察cpu和i/o的使用情况

# 间隔 1 秒输出 10 组数据
$ dstat 1 10
You did not select any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read  writ| recv  send|  in   out | int   csw
  0   0  96   4   0|1219k  408k|   0     0 |   0     0 |  42   885
  0   0   2  98   0|  34M    0 | 198B  790B|   0     0 |  42   138
  0   0   0 100   0|  34M    0 |  66B  342B|   0     0 |  42   135
  0   0  84  16   0|5633k    0 |  66B  342B|   0     0 |  52   177
  0   3  39  58   0|  22M    0 |  66B  342B|   0     0 |  43   144
  0   0   0 100   0|  34M    0 | 200B  450B|   0     0 |  46   147
  0   0   2  98   0|  34M    0 |  66B  342B|   0     0 |  45   134
  0   0   0 100   0|  34M    0 |  66B  342B|   0     0 |  39   131
  0   0  83  17   0|5633k    0 |  66B  342B|   0     0 |  46   168
  0   3  39  59   0|  22M    0 |  66B  342B|   0     0 |  37   134

要解决僵尸进程需要找出父进程,也就是它们的根

# -a 表示输出命令行选项
# p 表 PID
# s 表示指定进程的父进程
$ pstree -aps 3084
systemd,1
  └─dockerd,15006 -H fd://
      └─docker-containe,15024 --config /var/run/docker/containerd/containerd.toml
          └─docker-containe,3991 -namespace moby -workdir...
              └─app,4009
                  └─(app,3084)

09 | 基础篇:怎么理解Linux软中断?

Linux中的中断处理程序分为上半部分和下半部分

上半部分对应硬件中断,用来快速处理中断

下半部对应软中断,用来异步处理上半部分未完成的工作

 

10 | 案例篇:系统的软中断CPU使用率升高,我该怎么办?

 机器A运行以下命令:

docker run -itd --name=nginx -p 80:80 nginx

 

机器B运行hping3,发起syn flood攻击,此操作会导致目标主机网络高延迟,ssh连上去敲命令卡顿,甚于无法操作,解决方案是从交换机或硬件防火墙封掉攻击ip,这样SYN FLOOD网络帧就不会发送到服务器:

# -S 参数表示设置 TCP 协议的 SYN(同步序列号),-p 表示目的端口为 80
# -i u100 表示每隔 100 微秒发送一个网络帧
# 注:如果你在实践过程中现象不明显,可以尝试把 100 调小,比如调成 10 甚至 1
$ hping3 -S -p 80 -i u100 192.168.0.30

 

机器A进行问题排查

watch -d cat /proc/softirqs
                    CPU0       CPU1
          HI:          0          0
       TIMER:    1083906    2368646
      NET_TX:         53          9
      NET_RX:    1550643    1916776
       BLOCK:          0          0
    IRQ_POLL:          0          0
     TASKLET:     333637       3930
       SCHED:     963675    2293171
     HRTIMER:          0          0
         RCU:    1542111    1590625

通过 /proc/softirqs 文件内容的变化情况,你可以发现, TIMER(定时中断)、NET_RX(网络接收)、SCHED(内核调度)、RCU(RCU 锁)等这几个软中断都在不停变化。

其中,NET_RX,也就是网络数据包接收软中断的变化速率最快。而其他几种类型的软中断,是保证 Linux 调度、时钟和临界区保护这些正常工作所必需的,所以它们有一定的变化倒是正常的。

sar 可以用来查看系统的网络收发情况,还有一个好处是,不仅可以观察网络收发的吞吐量(BPS,每秒收发的字节数),还可以观察网络收发的 PPS,即每秒收发的网络帧数。

# -n DEV 表示显示网络收发的报告,间隔 1 秒输出一组数据
$ sar -n DEV 1
15:03:46        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
15:03:47         eth0  12607.00   6304.00    664.86    358.11      0.00      0.00      0.00      0.01
15:03:47      docker0   6302.00  12604.00    270.79    664.66      0.00      0.00      0.00      0.00
15:03:47           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
15:03:47    veth9f6bbcd   6302.00  12604.00    356.95    664.66      0.00      0.00      0.00      0.05

对网卡 eth0 来说,每秒接收的网络帧数比较大,怀疑是网络接收中断的问题。

那么,有没有办法知道这是一个什么样的网络帧,以及从哪里发过来的呢?

使用 tcpdump 抓取 eth0 上的包就可以了。

# -i eth0 只抓取 eth0 网卡,-n 不解析协议名和主机名
# tcp port 80 表示只抓取 tcp 协议并且端口号为 80 的网络帧
$ tcpdump -i eth0 -n tcp port 80
15:11:32.678966 IP 192.168.0.2.18238 > 192.168.0.30.80: Flags [S], seq 458303614, win 512, length 0
...

Flags [S] 则表示这是一个 SYN 包。

再加上前面用 sar 发现的, PPS 超过 12000 的现象,现在我们可以确认,这就是从 192.168.0.2 这个地址发送过来的 SYN FLOOD 攻击。

 

11 | 套路篇:如何迅速分析出系统CPU的瓶颈在哪里?

 

12 | 套路篇:CPU 性能优化的几个思路 

CPU优化分为应用程序优化和系统优化。

应用程序优化:编译器优化、算法优化、异步处理、多线程代替多进程、善用缓存

系统优化:CPU绑定、CPU独占、优先级调整、为进程设置资源限制、NUMA(Non-Uniform Memory Access) 优化、中断负载均衡

 




Buffer既可以用作“将要写入磁盘数据的缓存”,也可以用作“从磁盘读取数据的缓存”

Cache既可以用作“从文件读取数据的页缓存”,也可以用作“写文件的页缓存”

 

OSI网络模型

应用层--->表示层-->会话层-->传输层-->网络层-->数据链路层-->物理层

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值