0
点赞
收藏
分享

微信扫一扫

告别资源浪费!学会这招,硬件资源可达最优利用!

针对打开首页接口的性能问题,前文中确定是Gateway在消耗响应时间,达到了近100毫秒。于是,我们开始定位Gateway上的响应时间消耗。

  • 第一阶段,关注应用所在的主机,了解到宿主机有四台
  • 第二阶段,查看物理机的CPU模式。尝试通过修改CPU运行模式来优化性能。可仍没解决,TPS没见提升,响应时间依旧很长

进入第三阶段,继续分析其他瓶颈点,如wa cpu、资源均衡使用、网络带宽等问题。性能的分析逻辑里,资源均衡使用易被忽略,但又极为重要。通常都盯计数器给出的数值是否异常,而不考虑资源怎么做相应调配。

这案例系统是用k8s管理资源,所以须关注资源的均衡使用,避免出现有些服务性能差,却和性能好的服务分配同样资源。网络资源在k8s会跨好几层,也要着重关注。

请你多思考资源的均衡使用问题。来一起定位gateway上的响应时间消耗。

1 第三阶段:NFS服务器的wa cpu偏高

根据分析的逻辑,仍先看全局监控数据。查全局监控计数器,得到如下视图:

1[root@lenvo-nfs-server ~]# top2top - 00:12:28 up 32 days,  4:22,  3 users,  load average: 9.89, 7.87, 4.713Tasks: 217 total,   1 running, 216 sleeping,   0 stopped,   0 zombie4%Cpu0  :  0.0 us,  4.0 sy,  0.0 ni, 34.8 id, 61.2 wa,  0.0 hi,  0.0 si,  0.0 st5%Cpu1  :  0.0 us,  4.7 sy,  0.0 ni, 27.8 id, 67.6 wa,  0.0 hi,  0.0 si,  0.0 st6%Cpu2  :  0.0 us,  6.1 sy,  0.0 ni,  0.0 id, 93.9 wa,  0.0 hi,  0.0 si,  0.0 st7%Cpu3  :  0.0 us,  7.6 sy,  0.0 ni,  3.4 id, 82.8 wa,  0.0 hi,  6.2 si,  0.0 st8KiB Mem :  3589572 total,    82288 free,   775472 used,  2731812 buff/cache9KiB Swap:  8388604 total,  8036400 free,   352204 used.  2282192 avail Mem

计数器wa的CPU使用率偏高,Cpu2的wa已达90%。

wa cpu指CPU读写时,所产生的IO等待时间占CPU时间的百分比

这么高是因为写操作很多吗?就要关注IO状态,因为IO慢绝对是性能问题。

iostat看IO状态:

1[root@lenvo-nfs-server ~]# iostat -x -d 12Linux 3.10.0-693.el7.x86_64 (lenvo-nfs-server)  2020年12月26日   _x86_64_  (4 CPU)3..................4Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util5sda               0.00     0.00   94.00   39.00 13444.00 19968.00   502.44   108.43  410.80   52.00 1275.59   7.52 100.00678Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util9sda               0.00    18.00  137.00  173.00 17712.00 43056.00   392.05   129.46  601.10   38.80 1046.38   3.74 115.9010..................

IO使用率达100%,说明IO过程实在太慢。

再查Block Size,算一下当前IO到底是随机读写还是顺序读写。虽然大部分操作系统都默认Block Size是4096,但是,本着不出小错的原则,我们还是查一下比较放心。

先确定磁盘格式:

1[root@lenvo-nfs-server ~]# cat /proc/mounts2...................3/dev/sda5 / xfs rw,relatime,attr2,inode64,noquota 0 04...................5[root@lenvo-nfs-server ~]#

XFS格式,继续查看Block Size:

1[root@lenvo-nfs-server ~]# xfs_info /dev/sda52meta-data=/dev/sda5              isize=512    agcount=4, agsize=18991936 blks3         =                       sectsz=512   attr=2, projid32bit=14         =                       crc=1        finobt=0 spinodes=05data     =                       bsize=4096   blocks=75967744, imaxpct=256         =                       sunit=0      swidth=0 blks7naming   =version 2              bsize=4096   ascii-ci=0 ftype=18log      =internal               bsize=4096   blocks=37093, version=29         =                       sectsz=512   sunit=0 blks, lazy-count=110realtime =none                   extsz=4096   blocks=0, rtextents=011[root@lenvo-nfs-server ~]#

4096,也可看到读写基本都是顺序,不是随机。

来计算一条数据,确认一下

顺序写的能力

若全是随机写:

告别资源浪费!学会这招,硬件资源可达最优利用!_网络带宽

但实际写只有173次,所以确实是顺序写。

如果一次写了多个block就显然是顺序写;如果一次只写一个block就显然是随机写。

一次写多少个Block?

$(43056\times1024)\div173\div4096\approx 62个$

计算次数哪里为啥使用的43056而不是上面util100%对应的写19968?这里要用字节数来算,不能用使用率来算。

我们得出,一次写62个Block。从这样的数据来看,说明顺序写的能力还是不错的。因为对普通磁盘来说,应用在读写的时候,如果是随机写多,那写的速度就会明显比较慢;如果顺序写多,那么写的速度就可以快起来。

你发现了吗?虽然当前磁盘的顺序写能力不错,但是等待的时间也明显比较多。所以,接下来,我们得查一下是什么程序写的。这里我们用iotop命令查看:

1Total DISK READ :      20.30 M/s | Total DISK WRITE :    24.95 M/s2Actual DISK READ:      20.30 M/s | Actual DISK WRITE:       8.27 M/s3  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                  412180 be/4 root        2.39 M/s   16.01 M/s  0.00 % 35.94 % [nfsd]512176 be/4 root        3.20 M/s    0.00 B/s  0.00 % 32.25 % [nfsd]612179 be/4 root        3.03 M/s    6.43 M/s  0.00 % 32.23 % [nfsd]712177 be/4 root        2.44 M/s  625.49 K/s  0.00 % 31.64 % [nfsd]812178 be/4 root        2.34 M/s 1473.47 K/s  0.00 % 30.43 % [nfsd]912174 be/4 root        2.14 M/s   72.84 K/s  0.00 % 29.90 % [nfsd]1012173 be/4 root        2.91 M/s  121.93 K/s  0.00 % 24.95 % [nfsd]1112175 be/4 root     1894.69 K/s   27.71 K/s  0.00 % 24.94 % [nfsd]12...............

可见,IO都是NFS写过来的。那NFS的流量又从哪来?从下面数据看,这些流量从各个挂载了NFS盘的机器写过来,这是我们一开始部署应用时,考虑统一使用NFS来做IO的思路。因为这个机器挂载了一个大容量磁盘,为保证磁盘够用,就把多个主机挂载了NFS盘。

iftop命令:

1                    191Mb               381Mb               572Mb               763Mb          954Mb23172.16.106.119:nfs                   => 172.16.106.130:multiling-http        1.64Mb  2.04Mb  3.06Mb4                                     <=                                      26.2Mb  14.5Mb  19.8Mb5172.16.106.119:nfs                   => 172.16.106.100:apex-mesh             1.43Mb  2.18Mb  3.79Mb6                                     <=                                      25.5Mb  14.2Mb  14.4Mb7172.16.106.119:nfs                   => 172.16.106.195:vatp                   356Kb  1.27Mb  1.35Mb8                                     <=                                      9.71Mb  7.04Mb  7.41Mb9172.16.106.119:nfs                   => 172.16.106.56:815                    7.83Kb  4.97Kb  4.81Kb10                                     <=                                       302Kb   314Kb   186Kb11172.16.106.119:nfs                   => 172.16.106.79:device                 11.0Kb  7.45Kb  7.57Kb12                                     <=                                      12.4Kb  22.0Kb  28.5Kb13172.16.106.119:ssh                   => 172.16.100.201:cnrprotocol           2.86Kb  2.87Kb  5.81Kb14                                     <=                                       184b    184b    525b15169.254.3.2:60010                    => 225.4.0.2:59004                      2.25Kb  2.40Kb  2.34Kb16                                     <=                                         0b      0b      0b17169.254.6.2:60172                    => 225.4.0.2:59004                      2.25Kb  2.40Kb  2.34Kb18                                     <=                                         0b  0b  0b19172.16.106.119:nfs                   => 172.16.106.149:986                      0b   1.03Kb   976b20                                     <=                                         0b   1.26Kb  1.11Kb2122TX:             cum:   37.0MB   peak:   31.9Mb                      rates:   3.44Mb  5.50Mb  8.22Mb23RX:                     188MB            106Mb                               61.8Mb  36.2Mb  41.8Mb24TOTAL:                  225MB            111Mb                               65.2Mb  41.7Mb  50.1Mb

在Total DISK WRITE和Total DISK READ可看到,读写能力才 20M。没办法,既然wa这机器能力不好,就只有放弃统一写的思路。不过,为不让机器IO能力差成为应用瓶颈点,再尝试:

  1. 把MySQL的数据文件移走
  2. 把Log移走

接着执行场景,希望结果能好。

可查看TPS和RT曲线后,发现结果没改善。TPS依然很低且动荡大:

告别资源浪费!学会这招,硬件资源可达最优利用!_java_02

令人遗憾,那就不得不来到第四阶段。

2 第四阶段:硬件资源耗尽,但TPS仍然很低

先查全局监控的数据。看所有主机的Overview资源:

告别资源浪费!学会这招,硬件资源可达最优利用!_java_03

可见虚拟机k8s-worker-8的CPU使用率已很高,达95.95%。登录到这台虚拟机看更详细的全局监控数据:

告别资源浪费!学会这招,硬件资源可达最优利用!_数据_04

因为CPU不超分了,所以很明显看到,k8s-worker-8中的CPU被耗尽。从进程上看,CPU是被当前正在测试的接口服务消耗的。并且在这台虚拟机上,不止有Portal这一个进程,还有很多其他服务。

那就把Portal服务调度到一个不忙的worker,如移worker-3(6C16G):

告别资源浪费!学会这招,硬件资源可达最优利用!_网络带宽_05

得到:

告别资源浪费!学会这招,硬件资源可达最优利用!_数据_06

TPS已有所上升,达到300,性能确实变好。但这数据还不如一开始不优化的结果,毕竟一开始还能达到300TPS。接着分析当前瓶颈。

先看主机的性能数据:

告别资源浪费!学会这招,硬件资源可达最优利用!_数据_07

worker-8 CPU使用率达90.12%。为何这CPU还如此高?继续top看worker-8性能数据:

告别资源浪费!学会这招,硬件资源可达最优利用!_java_08

process中,排在第一的Gateway服务进程消耗CPU最多。

那就看这进程中的线程是不是都在干活:

告别资源浪费!学会这招,硬件资源可达最优利用!_数据_09

上图全绿,即Gateway中线程一直处Runnable态,看来工作线程确实挺忙。而前面的worker-8性能数据中,si cpu已达16%。结合这点,看实时的软中断数据:

告别资源浪费!学会这招,硬件资源可达最优利用!_网络带宽_10

可见,网络软中断一直往上跳,说明确实是网络软中断导致si cpu变高。网络软中断的变化是根据证据链找下来的:

告别资源浪费!学会这招,硬件资源可达最优利用!_java_11

看网络带宽多大:

告别资源浪费!学会这招,硬件资源可达最优利用!_网络带宽_12

倒是不大。从上述Gateway的工作线程、软中断数据和网络带宽情况来看,Gateway只负责转发,并无业务逻辑,也没啥限制。所以,针对TPS上不去原因,似乎除了网络转发能力较差,也找不到其他解释。

这个思路需要一些背景知识,因为我们通常用网络带宽判断网络是不是够用,但这还不够。在网络中,当小包过多,网络带宽是难以达到线性流量的。所以,这里的网络带宽即便不高,也会导致网络软中断的增加和队列的出现。

理解线性流量:假设一个包是1M,那总带宽是100M的话,需要100个包就行。若一个包只有10bit,那就不可能用完100M的总带宽。

既然如此,那就把Gateway也从worker-8移到worker-2(6C 16G),做这一步是为减少网络软中断的争用。

再看下集群整体性能:

告别资源浪费!学会这招,硬件资源可达最优利用!_数据_13

看起来不错,worker-8 CPU 使用率降到 56.65%,同时worker-3 CPU 使用率升到 70.78%。不过网络带宽有几个地方变红了,这后面再分析。至少从这里看到,压力是起来了。

回看压力情况:

告别资源浪费!学会这招,硬件资源可达最优利用!_网络带宽_14

TPS已达1000!棒!画个TPS对比图:

告别资源浪费!学会这招,硬件资源可达最优利用!_java_15

至此,打开首页接口的基准场景就能结束,因为我们已优化到比需求还高的程度。只是从技术角度,一个系统优化到最后是会有上限,所以,仍要知道这上限在哪。

3 第五阶段:硬件资源还是要用完

现在压力把worker-3的CPU资源用得最高,用到70.78%。那下面就把这机器的硬件资源用完,这才能判断系统容量的最上限。

要将性能优化分两阶段:

  • 把资源用起来
  • 把容量调上去

就算不是CPU资源,把其他资源用完也可。

既然这时压力已将worker-3 CPU用到70.78%,就到这应用中看线程把CPU用得咋样:

告别资源浪费!学会这招,硬件资源可达最优利用!_java_16

这里的线程确实都忙起来了。

既然如此,把Tomcat和JDBC连接的最大值都改到80,再看TPS(这只是个尝试,改大即可,没啥道理。后续测试过程,还要根据实际情况调整,就是不能让线程太大,也不能不够用)。

为让压力能直接压到一个节点,我们跳过Ingress,用分段的测法直接把压力发到服务。然后,去Pod设置一个node port把服务代理出来,再修改一下压力脚本。得到:

告别资源浪费!学会这招,硬件资源可达最优利用!_网络带宽_17

TPS还是抖动大,接着看全局监控:

告别资源浪费!学会这招,硬件资源可达最优利用!_java_18

有几个主机的带宽都红,而其他资源使用率并没有特别高。分析网络问题,不应只看网络带宽,还要分析其他内容,下面就得分析网络带宽。

到监控工具中看网络的流量,看到确实有一些非被测应用在占用带宽,且占得不小:

告别资源浪费!学会这招,硬件资源可达最优利用!_java_19

再看总体带宽,已用4G多:

告别资源浪费!学会这招,硬件资源可达最优利用!_数据_20

为弄清那些与被测系统无关的应用,会对带宽消耗产生影响进而影响TPS,先把影响带宽的应用都删除,如Weave Scope、Monitoring的监控工具等,从列表中看这些应用占不小带宽。

再次测试,发现TPS有所上升,稳定很多:

告别资源浪费!学会这招,硬件资源可达最优利用!_java_21

TPS已上升到1200,可见带宽对TPS还是造成不小影响。

接着,查网络的队列,发现应用所在的服务器(应用的所有的服务器)上面已经出现不小的 Recv_Q。

1Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name     Timer2tcp      759      0 10.100.69.229:8085      10.100.140.32:35444     ESTABLISHED 1/java               off (0.00/0/0)3tcp      832      0 10.100.69.229:34982     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4871.85/0/0)4tcp     1056      0 10.100.69.229:34766     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4789.93/0/0)5tcp      832      0 10.100.69.229:35014     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4888.23/0/0)6tcp     3408      0 10.100.69.229:34912     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4855.46/0/0)7tcp     3408      0 10.100.69.229:35386     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (5019.30/0/0)8tcp     3392      0 10.100.69.229:33878     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4495.01/0/0)9tcp      560      0 10.100.69.229:35048     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4888.23/0/0)10tcp     1664      0 10.100.69.229:34938     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4855.46/0/0)11tcp      759      0 10.100.69.229:8085      10.100.140.32:35500     ESTABLISHED 1/java               off (0.00/0/0)12tcp      832      0 10.100.69.229:35114     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4921.00/0/0)13tcp     1056      0 10.100.69.229:34840     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4822.69/0/0)14tcp     1056      0 10.100.69.229:35670     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (5117.60/0/0)15tcp     1664      0 10.100.69.229:34630     10.96.224.111:3306      ESTABLISHED 1/java               keepalive (4757.16/0/0)

从这看,网络已成下一瓶颈。

如果你想接着调优,还可以从应用代码下手,让应用处理得更快。不过,对于基准测试来说,一个没有走任何缓存的接口,在一个6C16G的单节点虚拟机上能达到这么高的TPS,差不多了。

还要去折腾其他接口,对这接口的优化到这里就结束了。

告别资源浪费!学会这招,硬件资源可达最优利用!_数据_22

4 总结

在打开首页这个接口的基准场景中,涉及到了很多方面的内容。从一开始的信息整理,比如访问路径、查看代码逻辑、场景试运行等,都是在为后面的分析做准备。

  • st cpu高时,看宿主机的CPU运行模式
  • wa cpu高的时候,看cat /proc/interrupts cat /proc/softirqs 找到对应的模块和模块的运行原理,最后找出解决方案
  • 为什么要把硬件资源用完?找到系统容量的上限

而当我们看到响应时间高,然后做拆分时间这一步,就是我一直在RESAR性能工程中强调的“分析的起点”。因为在此之前,我们用的都是压力工具上的数据,只是把它们罗列出来就好了,没有任何分析的部分。

对于拆分时间,我们能用的手段有多种,你可以用你喜欢的方式,像日志、APM工具,甚至抓包都是可以的。拆分了时间之后,我们就要分析在某个节点上响应时间高的时候,要怎么做。这时就用到了我一直强调的“全局-定向”监控分析思路。

在每一个阶段,你一定要清楚地定义优化的方向和目标,否则容易迷失方向。特别是对于一些喜欢把鼠标操作得特别快的同学,容易失去焦点,我劝你慢点操作,想清楚下一步再动。

而我们上述整个过程,都依赖于我说的性能分析决策树。从树顶往下,一层层找下去,不慌不乱,不急不燥。只要你想,就能做到。

举报

相关推荐

0 条评论