目录
背景
近期遇到一个问题。两台不同硬件型号的服务器,其CPU、内存的数量一致,且网络带宽也都够用。但是A服务器总时比B服务器下载速度要慢。A服务器内网下载速度在300MB/s,B服务器下载速度能到700MB/s。
其实不难猜到,硬件性能的差异,可能会导致这一情况的发生。但是具体是因为哪些因素影响呢?两台服务器都没有明显的性能瓶颈,那么应该优化那些性能才能提升这个下载速度呢?
先说结论
对于wget而言,网络带宽、内存&脏页相关内核参数、CPU、磁盘吞吐上限,都会成为下载速度限制的瓶颈。他们之间的关系是:
- 如果网络带宽不足,wget下载速度会直接被网络带宽所限制;
- 如果网络带宽充足,wget下载速度可以突破磁盘吞吐上限,因为wget下载会先写入内存缓冲区;
- 如果内存充足,脏页相关内核参数配置合理。下载的文件可以充分利用写入内存所带来的速度。那么wget下载速度会受到单核CPU性能限制,单核性能越高,下载速度越快;
- 如果内存不充足,但脏页相关参数配置合理。下载文件较大时,由于内存不够用,需要提前被强制落盘,那么此时磁盘吞吐上限就决定了wget的下载速度。
受限因素测试
1.网络带宽因素
测试前提:控制变量,使用相同CPU型号的服务器。但是CPU、内存数量存在差异。
当网络带宽不够充足时
测试场景:2CPU、8GB内存、内网带宽1Gbps、磁盘吞吐上限100MB/s,下载2GB大小文件。
结果:下载速度瓶颈127MB/s,被1Gbps带宽限制。
当内网带宽足够充足时
测试场景1:16CPU、64GB内存、内网带宽5Gbps、磁盘吞吐上限100MB/s,下载2GB大小文件。
测试场景2:32CPU、128GB内存、内网带宽10Gbps、磁盘吞吐上限100MB/s,下载2GB大小文件。
结果:当网络带宽没有瓶颈时,下载速度稳定在350-400MB/s。同时证明当网络带宽没有瓶颈时,CPU、内存的数量不影响下载速度。
结论1
- 网络带宽充足时,下载速度最终会稳定在一个区间。有除了网络带宽外的因素影响下载速度;
- 网络带宽充足时,CPU和内存的数量(足够用)不直接影响下载速度;
- wget场景下,数据会写入内存缓冲区。所以在缓冲区足够用时,磁盘读写吞吐限制也不会成为瓶颈。
2.内存&脏页内核参数因素
脏页内核参数概述
内核参数 | 解释 |
dirty_background_bytes | 是启动后台写入脏数据操作的阈值(以字节为单位)。 当系统中的脏数据量达到这个值时,pdflush/flush/kdmflush等内核线程会开始工作,尝试将一部分脏数据异步地写回磁盘以避免阻塞。 0 表示未配置此设置取决于基于百分比的设置(dirty_background_ratio) |
dirty_background_ratio | 表示启动后台写入操作的脏数据比例阈值。它与 dirty_background_bytes 的作用相同。 |
dirty_bytes | 系统中允许的最大脏数据量(以字节为单位)。 当系统中的脏数据达到这个阈值时,发起脏数据写入的进程会被阻塞,直到脏数据的数量减少到低于此值。 0 表示未配置此设置取决于基于百分比的设置(dirty_ratio) |
dirty_ratio | 是系统中允许的最大脏数据比例(相对于系统总内存的百分比)。这个参数与 dirty_bytes 的作用相同。 |
dirty_expire_centisecs | 指的是脏数据在内存中可以存在的最大时间(以百分之一秒为单位)。当脏数据的年龄(即在内存中存在的时间)达到这个值时,这些脏数据必须被写回到磁盘。 |
dirty_writeback_centisecs | 是控制 pdflush/flush/kdmflush 等后台写入线程唤醒频率的参数(以百分之一秒为单位)。这个参数决定了后台线程多久检查一次是否需要写回脏数据。 |
举个栗子:
dirty_background_bytes 0
dirty_background_ratio 10
dirty_bytes 0
dirty_ratio 40
dirty_expire_centisecs 3000
dirty_writeback_centisecs 500
-
dirty_background_bytes 和 dirty_bytes 为0,则配置由dirty_background_ratio 和 dirty_ratio生效。
-
当内存脏页 小于 dirty_background_ratio 配置的10%时。dirty_writeback_centisecs每5秒唤醒一次检查是否需要写回脏数据,由于内存脏页没有达到 dirty_background_ratio 配置的阈值,将不会被回写。直到达到 dirty_expire_centisecs 配置的30秒阈值,脏数据被强制回写到硬盘。
-
当内存脏页 大于 dirty_background_ratio 配置的10%,但 小于 dirty_ratio 配置的40%时。dirty_writeback_centisecs每5秒唤醒一次检查是否需要写回脏数据,发现内存脏页达到了 dirty_background_ratio 配置的阈值,尝试将一部分脏数据异步地写回磁盘以避免阻塞。
-
当内存脏页达到 dirty_ratio 配置的40%时。脏页被写回磁盘。
当内存足够时
测试场景:16CPU、64GB内存、内网带宽5Gbps、磁盘吞吐上限110MB/s,下载2GB大小文件。
内核参数
结果:由于有充足的内存作为缓存,wget下载2GB文件期间,数据全部进入内存缓存而没有落盘。所以wget速度远高于磁盘吞吐上限。iostat命令也可以看到磁盘的写入吞吐wMB/s一直为0。
当内存不足时
测试场景:16CPU、64GB内存、内网带宽5Gbps、磁盘吞吐上限110MB/s,下载2GB大小文件。
内核参数(通过调小可用的内存脏页大小,模拟内存不够的情况)
结果:64GB内存,内存脏页上限1%,可用内存脏页600+MB。观察wget下载。
刚开始数据可以正常写入内存脏页,速度仍然300+MB/s。
当超过 dirty_ratio 设置的阈值后,内存脏页中的数据强制写入磁盘,磁盘写吞吐达上限(110MB/s),wget速度也开始变慢。
结论2
- 服务器内存足够大时,配合脏页内核参数。wget下载文件不会直接落盘,极大地提高了速度;
- 服务器内存不足时,内存脏页内核参数 dirty_ratio 强制回写脏数据到磁盘。此时的下载速度会与磁盘的性能挂钩。
3.CPU性能因素
准备A、B、C三台服务器,除了CPU型号不一样外,CPU数量、内存数量、存脏页内核参数、磁盘吞吐、网络带宽内均一致。
测试场景1:直接wget下载文件,测试三台服务器wget下载速度上限
服务器 | CPU型号 | 下载速度 |
A | 2.5 GHz主频的Intel ® Xeon ® Platinum 8163(Skylake)或者8269CY(Cascade Lake) | 300+MB/s |
B | 2.5 GHz主频的Intel ® Xeon ® Platinum 8269CY(Cascade Lake),睿频3.2 GHz | 500+MB/s |
C | 第三代Intel® Xeon®可扩展处理器(Ice Lake),基频2.7 GHz,全核睿频3.5 GHz | 700+MB/s |
A服务器:
B服务器:
C服务器:
测试场景2:限定wget下载速度,测试三台服务器单核使用率
使用wget --limit-rate=100M 限定下载速度
使用pidstat去跟踪wget使用CPU的情况:wgetPID=$(ps -ef | grep wget | grep -v grep | awk '{print $2}') && pidstat -p ${wgetPID} -t 1
服务器 | CPU型号 | 单核使用率 |
A | 2.5 GHz主频的Intel ® Xeon ® Platinum 8163(Skylake)或者8269CY(Cascade Lake) | 20%-30% |
B | 2.5 GHz主频的Intel ® Xeon ® Platinum 8269CY(Cascade Lake),睿频3.2 GHz | 18%-21% |
C | 第三代Intel® Xeon®可扩展处理器(Ice Lake),基频2.7 GHz,全核睿频3.5 GHz | 10%-15% |
A服务器:
B服务器:
C服务器:
结论3
- 当网络带宽和内存大小都不存在瓶颈时。因为wget是单线程的,所以wget下载速度,取决于单核CPU的性能。单核CPU性能越好,下载速度越快。
4.磁盘写入带宽因素
同一台服务器,CPU、带宽不存在瓶颈,模拟内存存在瓶颈,数据直接落盘。准备多块不同性能的磁盘,对比落盘速度对wget下载速度的影响。
测试场景:调整内存脏页内核参数,模拟内存存在瓶颈。直接wget下载文件进行对比。
内核 参数
磁盘吞吐上限 | wget下载速度 |
110MB/s | 120MB/s |
200MB/s | 230MB/s |
300MB/s | 370MB/s |
结论4
- 当内存资源不足时,wget写入内存脏页的数据会被强制落盘,届时wget下载速度会受到磁盘吞吐上限的限制。
5.关于wget的写数据逻辑
iotop命令可以相对准确辨别出,wget命令在下载时何时在写入内存,何时在写入磁盘。
iotop关注指标:
-
Total DISK WRITE "Total DISK WRITE" 表示通过或与进程相关的所有写入操作的总量,包括实际的磁盘写入以及仅仅写入到了操作系统的缓存中的写入操作。
-
Actual DISK WRITE "Actual DISK WRITE" 表示的是实际写入到磁盘的数据量。
wget下载中,写入内存缓存时:
wget速度突破磁盘吞吐上限;iotop "Total DISK WRITE" 显示了写缓存的速度;iostat命令显示磁盘此时没有数据写入。
wget下载结束,内存缓存落盘时:
wget已结束;iotop "Actual DISK WRITE" 显示了实际落盘速度;iostat命令显示磁盘此时有数据写入。