极客时间已完结课程限时免费阅读

28丨案例:带宽消耗以及Swap(下)

28丨案例:带宽消耗以及Swap(下)-极客时间

28丨案例:带宽消耗以及Swap(下)

讲述:高楼

时长28:35大小22.90M

上一篇文章我主要分析了带宽消耗,今天,我们来看一下分析的第二和第三阶段,也就是 Swap 分析和数据库分析。

分析的第二阶段

Swap 的原理和对 TPS 的影响

前面有一个扣,是说 swap 多的问题。要理解 swap 为什么是黄的,得先知道什么是 swap。我先画个简易的示意图。
这里先解释一下,对于一个 Linux 系统来说,如果配置并开启了 swap 分区,那么默认的 swappiness 参数是 60。
swappiness 是在内存 reclaim 的时候生效的,而 reclaim 方式同时有两个动作:1. 将 file 相关内存进行回收;2. 将 anon 内存交换到 swap 分区。
所以 swapiness 值越大,swap 分区就用得越多。
对我们现在分析的这个系统来说,来看一下:
我们看到这里配置了一个内存为 8G 左右,已经使用了 7G 多了,swappiness 配置为 30%。
通过 free 看到现在只有 145M 的物理内存剩余,可用内存也只有 254M 了。
所以上面图中的 swap 飘黄也是很合理的喽!
下面我们就针对应用服务器的 swap 来看是不是可优化。
所有人都知道,当 swap 被用的时候,性能肯定会下降,所以在我的测试过程中,一般我都建议把 swap 直接关掉测试性能,有人说这样有什么问题?
那就是没有 swap,让不常用的对象直接占用物理内存,如果物理内存不够用,就把对象删了,后面再创建,这时会增加的是 major fault,那就增加好了,反正是要性能差的。
说得如此硬气,那在生产中怎么办呢?开还是关?有人觉得关了心里有安稳,有人觉得开着心里会安稳。而一个系统、一个容器、一个节点,如果容量控制的非常好的情况下,我建议关掉。开着它,也只是心里上的安慰,不会有 TPS 处理能力上的提升。

瓶颈分析定位

既然知道了上面的大概原理。对一个运行 Tomcat 应用的服务器来说,那肯定是要先检查一下 JVM 设置为多大。先执行 ps 命令,看一下 Java 进程吧。
关键参数如下:
JAVA_OPTS="$JAVA_OPTS -server -Xms2048M -Xmx8192m -XX:PermSize=256M -XX:MaxNewSize=2790m -XX:MaxPermSize=512m -XX:SurvivorRatio=8"
JVM 是 1.8.0_65。
这个参数配置有很大的问题。物理内存只有 8 个 G,一个 JVM heap 就配置了 8G,这让其他的东西怎么玩得起来?并且 JDK 是 1.8 了,配置 permsize 是又为啥呢?
虽说有多个地方配置不合理,但是我们也得要知道一下应该配置多少是合理的吧。
看参数的时候,JMX 也配置上了,那就用工具来看吧。
首先来看一下系统资源。先看一下系统资源在压力下的表现:
队列已经出现,CS 2 万多,in 2 万多,说多不多。我们可以先放着。
I/O 没什么压力,swap 也一直有值,我们要解决的就是它。
us:sy 接近 2:1,这个是不良信号,记在心里,后面再说。
其次再看下 JVM 的情况:
CPU 使用在应用上的时间达到 60%,GC 上没耗什么时间,并且从堆的回收能力上来看,比较正常,只是只用到了 3G 左右,这里有必要给 8G 吗?
线程活动的达到 347,看起来还是在增加的,这里也可能是个问题点,只是现在我们不用关心,它还没跳出来。
从这个 JVM 状态上来看,它完全用不到 8G。在这种状态下,还有另一个 Tomat,并且另一个 Tomcat 中也没有配置 -Xmx -Xms 参数,当没有配置时,默认 -Xmx 是物理内存的 1/4。再加上 thread 用的,所以 swap 飘黄也是吻合的。

优化结果

首先,我们把 JVM 配置成最简,JVM 设置为 4G。
JAVA_OPTS="$JAVA_OPTS -server -Xms4096M -Xmx4096m"
perm 区在 1.8 里都没有了,这几个参数也没啥用。在我的习惯中,MaxNewSize 也是先看要用到多少,再决定配置不配置。有些应用自己不熟悉,也无法直接给出配置,只有测试之后再配置。
各部分配置为多大,都没有定数,要通过测试看需要多少。
而我们现在最重要的是先把性能调整上去,再考虑这些细节内容。这样修改 JVM 就是为了把物理内存使用率低下来,先不修改 swapiness 的比例是为了看下结果,如果用不到 swap 就不再调了,如果还是用了 swap,再来调它。
当我们把 JVM 修改了之后,再执行起来场景。看到内容如下:
CPU 使用率相对前面没有什么变化,但是堆 4G 只用到了 1.5G,可见这个堆连 4G 都用不到。当然我们还是要分析下其他的内容。
还记得我们要解决的是什么问题吧?swap 飘黄了!
从这张图可以看到 Swapping 不报警了!CPU 占用 70% 左右。说明现在 available 的内存是充足的。
这时我们再看一下系统资源,首先是应用服务器系统资源。
应用服务器系统资源 vmstat 如下:
应用服务器系统资源 top:
应用服务器系统资源 iftop:
上图中可以看到,对比之前的资源,swap 基本上没有了,CPU 使用率多起来了。但是队列依旧长,sy CPU 消耗还是有点多了。
应用服务器的 si 已经到了 13.1% 了,这个值要关注下,暂时还不能说是问题,但是接着增加下去,肯定会是问题。
网络已经超过 70Mbps 了,峰值上到 87Mbps,这是一个好事,它说明现在处理的业务量确定多了。
接下来是数据库服务器系统资源:
你可以看到数据库 CPU 都用到这么高了?
TPS 能到 259.2 了,较之前的 221.5 没有提升多少。但是我们解决了 swap 的问题,还是有了一点点的提升。
那下一个瓶颈在哪里呢?通过上面的数据库资源来看,数据库早就已经被用到了 100% 的 CPU,队列也嗖嗖地涨到了好几十,高的都超过 100 了。
可见我们在处理应用服务器的时候,数据库这边已经早就吃不消了。那下面,我们就先把应用服务器的优化部分放一下,再去分析下一个短板:数据库。

后续性能工作建议

但是这里并不是说应用服务器的优化工作就完成了,还有一些部分需要做的。
优化 JVM 配置参数,至于应该配置成什么值,还需要再测试,可能会有人说,这个测试人员怎么知道呢?请你相信,如果这个值性能测试人员都测试不出来的话,一般的架构师也不可能知道该设置为多少。
通过监控分析确定 swapiness 的值。
网络带宽又快到占满了,如果 TPS 再提高,网络肯定又支撑不了。
这些扣也都放在这里。因为我们主要是找到系统的短板,并一一解决,才能使整体的 TPS 增加,虽说现在应用服务器上还有优化的空间,但是现在它不是最短的板。
我们在不忘记应用服务器这些问题的同时,再将目光转向数据库。

分析的第三阶段

瓶颈分析定位

先来看看数据库的系统资源。
我在很多场合都在强调一个词:证据链。所以基本上分析也会是从 OS 层面开始。
但是证据链这个词说起来容易理解,实际上要想真的有链起来的能力,必须具有基础知识,像分析数据库就更明显。因为当我们不了解系统架构时,想说明一个事情就非常困难。
像上面的这个 top,显然 us CPU 使用率非常地高,idle 几乎没有了,只有一个 si 占了 5.7%,这个 si 并不算高,我们在上一阶段看到的应用服务器的 si 都已经达到了 13% 了。
我们说 si 的高或者低,倒不是关键,关键的是它有没有成为我们的瓶颈点。在这个系统中,us cpu 才是我们要关注的重点,因为它实在是太高了。
对于一个数据库来说,要干的事情就是执行 SQL。当分析多了数据库之后,基本上也形成了套路。不管怎么样,还是先看一下基本的监控信息,以下截取一些 Spotlight on MySQL 的有用的图,如果你没有这个工具,用其他的监控工具也是一样的。
从上面的图可以看到,CPU 使用率 99%,Query Cache 是 OFF 的。记下这个位置!
从上图看到,负载队列非常长,但 Disk I/O 没多少,说明队列和I/O 无关,只是 CPU 的队列,非常好!
Network 也不算大,进出每秒 5000 多个包,我们再来看一下网络用到多少了?
峰值也才 70Mbps 左右,即使是 100Mbps 带宽,现在仍然认为有余量(注意!我这里说有余量是因为我同时也检查了网络队列,并没有阻塞,并不是只看了这个值就武断地做了判断)。
通过上面的图可以看到,每秒执行 2500-3000 的 SQL,Sorts per second 达到 800-1000,Sort rows per second 达到 8000-10000。
session 用得倒是也不多,但 Miss Rates 在压力过程中 Query Cache 都是在 100%,并且从最上面的 summary 中可以看到 Query Cache 也是 OFF 的。
为什么没有在看到 Query Cache 是 OFF 的时候就敲黑板呢,这是因为在一些应用中,如果不是查询多的话,这个值 OFF 也不能说有问题,但是在这个应用中几乎所有的语句都是 select,那这个 Query Cache 再不打开就说不过去了呀。这里先记录下这个问题,待会我们的优化动作就是打开 Query Cache。
不管怎么说,对一个数据库来说,主要是执行 SQL 嘛,而对 MySQL 来说,不看 slow log,还能看什么呢。
通过整理 slow log,看到如下内容:
# Overall: 280 total, 1 unique, 0.59 QPS, 9.53x concurrency ______________
# Time range: 2019-09-26T13:44:08 to 2019-09-26T13:52:06
# Attribute total min max avg 95% stddev median
# ============ ======= ======= ======= ======= ======= ======= =======
# Exec time 4555s 12s 19s 16s 18s 2s 16s
# Lock time 52ms 130us 662us 185us 273us 53us 167us
# Rows sent 0 0 0 0 0 0 0
# Rows examine 30.81M 112.69k 112.69k 112.69k 112.69k 0 112.69k
# Query size 186.48k 682 682 682 682 0 682
# Profile
# Rank Query ID Response time Calls R/Call V/M Item
# ==== ================== ================ ===== ======= ===== ===========
# 1 0xBED932B8C940697E 4555.0867 100.0% 280 16.2682 0.16 SELECT test2
什么情况?只有 1 unique?0.59TPS?我前面的 TPS 可是有 259.2,这结果一看就感觉不对。
查看一下 long_query_time,配置成了 10s,怪不得看不到慢 SQL。
改 long_query_time 为 1s,再跑一遍。看到如下结果:
# Overall: 620.47k total, 30 unique, 259.39 QPS, 16.76x concurrency ______
# Time range: 2019-09-26T13:44:08 to 2019-09-26T14:24:00
# Attribute total min max avg 95% stddev median
# ============ ======= ======= ======= ======= ======= ======= =======
# Exec time 40082s 88us 23s 65ms 323ms 649ms 332us
# Lock time 61s 30us 363ms 97us 152us 1ms 69us
# Rows sent 1.92M 0 633 3.25 21.45 7.43 0.99
# Rows examine 987.99M 0 112.69k 1.63k 10.29k 5.49k 420.77
# Query size 240.33M 89 1.52k 406.15 833.10 258.19 246.02
# Profile
# Rank Query ID Response time Calls R/Call V/M Item
# ==== ================== ================ ====== ======= ===== ==========
# 1 0x160FA75270C56FB8 22892.5442 57.1% 65352 0.3503 0.16 SELECT test1
# 2 0xBED932B8C940697E 15914.4501 39.7% 986 16.1404 0.44 SELECT test2
# 4 0xF0AE7AFA7851C7E8 245.0176 0.6% 175 1.4001 0.11 SELECT test3
# 5 0xFB5A64603A53BFCE 97.2016 0.2% 77 1.2624 0.04 SELECT test4
# 14 0x1E088E88CDC208BE 8.7701 0.0% 14 0.6264 0.23 SELECT test5
嗯,这看着顺眼多了。前两个 SQL 占了所有执行时间的 96.8%!第一个 SQL 平均执行时间 350ms,方差 16%。而第二个语句更夸张,平均执行时间 16s,方差 44%。这得收拾!
但是要不要优化这样的 SQL,我们就需要根据 SQL 的分析和业务的分析来判断了。这里我先把执行计划列出来看看。
SQL1 的执行计划:
没有分区。
不包含子查询或者 union 操作。
全表扫描。
第一个表所查有 70 行,第二个表所查有 631 行,此值仅做为参考,并不精准。
第一个表返回结果只占了读取行数的 1.43%(优化点),第二个表返回结果只占了 0.16%(优化点)。
在第一个表中,Extra 有一个值,using where。
在第二个表中,Extra 有一个值,Range checked for each record (index map: 0x1) 。
SQL2 的执行计划:
没有分区。
不包含子查询或者 union 操作。
非唯一索引查找,也列出了具体的索引。
第一个表索引列上有 102570 行,第二个表索引列上有 118 行。此值仅做为参考,并不精准。
第一个表返回结果只占了读取行数的 3.33%(优化点),第二个表返回结果占了 100%。
在第一个表中,Extra 有三个值,using index condition; using where; using filesort。
在第二个表中,Extra 有一个值,using where。
这里我要敲黑板了!!!你是不是不记得 Extra 这些值的含义了?是不是要祭出你的搜索引擎,要开始查了!
我们这里再来回顾一遍。
using where:对结果用 where 子句中的条件过滤。
Range checked for each record (index map: 0x1):MySQL 没有找到可以使用的索引,如果前面的表的列值已知,可能会部分使用索引。
using index condition:先条件过滤索引,找到所有符合索引条件的数据行,再用 where 子句中的条件做过滤。
using filesort:Query 中有 Order By 操作,又无法用索引完成排序,MySQL 不得不选择相应的排序算法来实现。是不是对应上了前面的 sorts per second?
知道了这些基础知识之后,下面再来看一下,两句语句很显然都有优化的空间,尽量使用 filtered 的比例能大一些,至于能不能用到索引,那就看业务的需要了,如果确实是要查很大的索引,表扫还能快点。所以这两个语句,要丢给开发做业务分析了。

优化结果

对数据库,我们有两个优化的方向还记得吧,第一个是 SQL 语句,第二个是 Query Cache。
我们先做第 2 个,将 Query Cache 开启,看一下效果如何。
mysql> show variables like 'query_cache%';
查看结果如下:
query_cache_type ON
query_cache_size 1048576
再执行起来场景,看系统资源:
效果还不错哦,us CPU 降到了 50% 以下。
网络峰值时能达到 90Mbps 了,又快把带宽占完了。
查看网络队列:
再检查下队列,这时看到已经有接收队列了。
从 TPS 上来看,现在能到 300 多一点,同时网络接收发送加在一起 8M 左右。

后续性能工作建议

接下来数据库的优化方向就是优化 SQL。
当然还有别的优化建议,我们将在后面再说。

总结

这个案例从一个概括的描述开始,到各阶段的分析定位,是一个非常完整的过程。从一个项目的角度上来说,现在是不是性能已经达标,要有两方面的判断。
技术方面来说,显然这系统还有很多优化的空间,我们在文中也留了不少的扣。
业务方面来说,系统是否可以上线,就取决于业务指标了。
但是这个性能是不是已经做得完整了呢?显然还没有。现在只是调了一个节点而已。因为这是在测试环境中做的,硬件环境显得非常简单。线上部署结构也会包括分布式多节点集群等。所以从一个性能项目的角度来说,还远远没有结束。我想如果把这个项目完整地写下来,一本书的容量应该不为过。
从技术细节上来说,通过几个阶段的具体操作,可以让你有一个性能分析定位的宏观感受,这也是这两篇内容的初衷。性能优化是无止境的,我们要做的是以最少的时间和金钱成本,达到最大的优化效果。

思考题

这一篇文章延续上一篇的分析思路,你能讲一下 Swap 的原理和逻辑,以及分析思路吗?另外,慢 SQL 如何定位出来呢?
欢迎你在评论区写下你的思考,也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。
分享给需要的人,Ta购买本课程,你将得18
生成海报并分享

赞 9

提建议

上一篇
27丨案例:带宽消耗以及Swap(上)
下一篇
29丨案例:如何应对因网络参数导致的TPS呈锯齿状?
unpreview
 写留言

精选留言(18)

  • Geek_8e5c47
    2020-03-04
    慢查询信息和网络信息是使用什么命令查看到的啊?

    作者回复: 网络是netstat。慢查询是pt-quest-digest。

    6
  • 小老鼠
    2020-03-21
    在虚拟机或dock环境中可进行性能测试吗?

    作者回复: 这个问题过于宽泛了,但是本着认真的态度,还是回复一下吧。 对于性能测试环境,只有一个可信的答案,那就是:和生产一致。 生产用什么配置,测试就用什么配置是最靠谱的。 但是我们经常会遇到的是硬件环境会有区别。所以经常会有人在硬件不同上钻牛角尖,而不去考虑系统特性以及什么资源影响最大。 如果是CPU资源使用最多,我们只要去对比CPU能力也能比较个大概。 而虚拟机和docker能不能用于性能测试?当然可以。不管什么环境,都可以用于性能测试。 而现在我们用于应用级别的机器基本上都是虚拟机和docker。这必然是可以用的。 其核心是,这套硬件能提供的能力到底是什么样。而不用纠结是虚拟机还是docker还是物理机。

    4
  • alley
    2021-01-17
    老师查看网络带宽满的命令是什么

    作者回复: 看带宽,要看使用率和队列两个角度。通常我是用iftop和netstat。你也可以用其他命令。

    3
  • 2020-05-24
    如果真得示客户网络带宽导致瓶颈,有什么推荐的方法,比如10M带宽,如果要扩大的话,需要怎么扩大。扩大的到什么程度,

    作者回复: 根据TPS来计算需要多少带宽,扩大的手段很明确。 外网的就只能买了。 内网就是换网络设备(路由、交换、网线、网卡等),就看是哪里限制的了。

    共 2 条评论
    2
  • nelson
    2020-05-11
    对于为什么打开查询缓存,没有给出相关的表和SQL,没有任何理论依据,而是直接打开缓存尝试。颇有实践主义的色彩。 现在十分不建议打开查询缓存,一旦数据更新之前费劲建立起来的缓存都全部清空了,另外实在命中率不高涂层消耗,除非在非常特殊的场景 另外在My SQL 8.0中,干脆废掉了查询缓存

    作者回复: 查询缓存的使用是有适用的场景的。在查询多的应用中,打开查询缓存是会有用的。

    共 3 条评论
    3
  • 每天晒白牙
    2020-03-21
    老师的功力太深厚了,感觉性能测试要会的东西很多,测试,开发,运维,架构等等,我是小开发,看这种排查问题的文章真是爽,要是能在工作中这样酣畅淋漓的排查,爽啊

    作者回复: 以后我尽量多写这样的。哈哈。

    3
  • 李大.shu
    2020-12-11
    老师,我在一次性能测试过程中,cache的值一直上升,然后将物理内存占满后,cache的值趋于稳定,程序用的used也趋于稳定(内存利用率在45%左右)。但通过vmstat统计观察swpd的值一直在上涨,通过jconsole查看也没有内存泄漏的问题。压测了48小时,tps和响应时间都在要求的指标范围内,这种情况算是正常情况吗,有没有风险,我担心swpd继续涨下去会有问题

    作者回复: 压时间长一点,看有没有oom。

    1
  • 孙奕意
    2020-12-08
    文中JVM截图是jconsole工具的?在liunx系统上也可以用jconsole 进行JVM监控的吗?

    作者回复: jvirsualvm,远程用jmx就能连。

    1
  • TavisD
    2020-04-01
    高老师,请教下JVM配置是用哪种测试场景去调优呢。比如系统有好几个应用,测试场景也有基准测试、混合测试,那是测基准测试时去调优JVM配置?还是混合测试时?还是所有的场景都要去做这个JVM调优配置?如果出现多个场景JVM的最佳配置不一样,是以哪个为准?

    作者回复: 这个没有区分,什么场景下发现问题就什么时候调。

    1
  • hello
    2020-02-24
    老师这两篇案例分析特别流畅,一口气看完,思路真的很清晰,感谢老师!

    作者回复: 多谢支持,你的收获就是我的动力。

    1
  • Rachel
    2021-12-28
    监控工具可以安装在独立于应用服务器、数据库服务器、压力机等之外机器吗?

    作者回复: 那就要有agent来收集数据了。

  • 林义的奥妙
    2021-11-03
    老师,JVM的堆设置为原来的一半之后,为什么使用率就降底到1.5G左右?

    作者回复: 文中的意思是因为jvm只用到1.5G才把因为降一半。

  • lin~
    2021-10-12
    老师,swap飘黄的逻辑有些疑问,这里swapiness设置为30,如果设置为80的话,在available mem不够的情况下还会飘黄么

    作者回复: 在性能测试中,不建议使用swap。

  • alley
    2021-01-11
    好厉害啊,干货满满,像侦探片一样,引人入胜。

    作者回复: 多谢支持鼓励。

  • 万伟
    2020-05-08
    您好,请问一下,Spotlight on Linux配置好ssh连接后,点connect为什么总报conection lost? 环境: 本地:win7 SpotlightonUnix_70.exe linux:centos7

    作者回复: 这个问题太笼统了。

  • tt
    2020-02-26
    应用开发人员,但是啥都可能干,包括部分运维,还有性能和安全。对我来说,这两节课我要记住的就是:主机(节点)压不出来,那就是路(网络)出了问题。 遇到过的问题是网络链接释放不干净,导致CLOSE_WAIT大量出现,最后内存使用过多,导致进城挂了的事。作为开发,那时还没有这么多分析操作系统的知识。只能从网络一点着手。 老师能不能再补充一些事故后的“尸检”环节呀?
    展开

    作者回复: 哈哈,啥叫尸检?

    共 2 条评论
  • 夜空中最亮的星
    2020-02-25
    这两篇案例很棒

    作者回复: 多谢支持,这样的案例我有很多。我只是随意选择几个。😀😀

  • 老姜
    2020-02-24
    mysql用的是什么监控工具?

    作者回复: 本篇用的是spotlight。

    1