Linux 性能调优之网络优化
写在前面
考试整理相关笔记
分享一些 Linux 中网络内核参数调优的笔记
理解不足小伙伴帮忙指正
对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》
网络优化
Linux 网络优化是一个很大的概念,这里讲的优化主要是 传输层
和网络层
的优化.
Linux
和其他主流操作系统中的网络流量
被抽象(协议分层与 OSI 参考模型)为一系列的硬件和软件层次
。在每个分层上,发送端添加首部包装信息,经过路由器,接受端分离首部恢复数据。当然路由器的传递也涉及网络层和链路层的首部分离和添加.
简单回顾:
数据的流向整体是一个出栈入栈的过程,用应用层开始,包装数据,化整为零,分段传输,然后到物理层为信号传输,这是进栈,到达目标 IP,在通过碎片缓存区
化零为整,出栈到达应用层。
传输层和网络层的数据流转
数据传输(出站) :
首先,应用程序通过操作系统提供网络套接字API(编程接口)
将数据写入到socket
文件描述符, 即数据被写入到 socket
文件,然后放到传输缓存
中,常见的协议包括 TCP(传输控制协议)和 UDP(用户数据报协议)。
这是时候操作系统内核
从传输缓存
中提取数据
,根据网络协议规范(TCP/UDP) 封装数据到一个PDU(协议数据单元,TCP段/UDP数据报)
,网络层会添加 IP 头部,形成 IP 数据报
。
将包含 PDU数据单元
的 IP 数据报
放到 设备传输队列
,等待发送,网络设备驱动程序
定期检查传输队列
,获取待发送的PDU
。驱动程序将PDU数据
从内核空间
拷贝到网卡设备(NIC)
的内存缓冲区
一旦PDU
被拷贝到网卡设备的内存缓冲区
,网卡设备开始发送数据。数据发送过程可能涉及物理层操作,例如将数据转换为电信号并发送到物理介质(例如以太网)。在数据传输过程中,网卡设备可能会引发中断,通知操作系统数据传输已完成或需要进一步处理。
这里要经过 路由寻址,地址转发
,到达目标 IP 主机,到达目标 IP 之后,会有个入栈操作
接受数据(入站) :
当数据帧
到达网卡时,网卡
会使用 DMA缓存区
将数据帧复制到接收缓冲区
。接收缓冲区
是在操作系统内核中为接收数据包而分配的一块内存区域,一旦数据帧被复制到接收缓冲区
,网卡会向主机发起硬中断
信号,通知操作系统有新的数据包
到达。
操作系统内核
接收到硬中断
信号后,会中断当前执行的任务,并进入硬中断
处理程序,在硬中断处理程序中,操作系统内核
会调度软中断
(软中断是一种延迟处理机制,它允许将数据包的处理推迟到适当的时机,以提高系统性能)来处理接收到的数据包。。
软中断
处理程序会从接收缓冲区
中读取数据包
,并进行必要的处理。这包括解析数据包的各个层级协议头部(例如以太网头部
、IP头部
等),将数据包移交给IP层
进行进一步的处理。
如果数据包大于 MTU(最大传输单元)
,需要分段传输,这里需要利用 碎片缓冲区
重新组装为原始数据报
内核封装数据到协议数据单元(PDU)
,对等分层间传输数据的单位,物理层
的 PDU 是位(bit)
,数据链路层
的 PDU 是数据帧(frame)
,网络层
的 PDU 是包(packet)
,更高层的 PDU 是数据报文(message)
. 一个 PDU 包括上层的数据
加本层的数据头部信息
。
网络内核调优
通过上面的简单回顾,可以了解到 网络缓存
包括内核缓存
,每个socket缓存
,碎片缓冲区
以及网卡的DMA缓冲区
。
可以通过配置上面不同的缓存区的内核参数达到调优的目的,具体的调优参数配置可以结合上面的图
系统级内核参数(对缓存的动作)
net.ipv4.tcp_mem,net.ipv4.udp_mem(单位是
Page 内存页,4K)
分别代表了TCP和UDP的系统层面内存限制的值
,即网络连接的内存分配,包括三列:min,pressure,max
, net.ipv4.tcp_mem
即我们常讲的 TCP 接收窗口大小
min
: TCP/UDP 使用低于这个值时,内核不会释放这些缓存。pressure
:当 TCP/UDP 缓存超过这个值时,内核开始释放缓存,减少使用量,直到低于 min 值。max
:所有 TCP/UDP 的 sockets 可以使用的最大内存缓存值。
注意
:net.ipv4.tcp_mem和net.ipv4.udp_mem
是 pages 为单位,不是字节为单位,可以使用 getconf PAGESIZE 查看 page 大小的值(一般是 4096 字节=4K)
查看内存页的大小
内核参数位置:
对于这两个参数的调优,在使用 sar
来查看链路级的网络性能数据
比如 sar -n EDEV 1 1
,显示每个设备的发送和接收错误信息
当 rxdrop/s
和 txdrop/s
存在数据时,可以适当调整上面的内核缓冲内核参数
需要注意的是计算大小的时候,需要使用 当前大小,乘以页数,得到 KB 在 除以 1024 得到 MB。
Socket 级别内核参数限制
net.core.rmem_max,net.core.wmem_max
socket接受
和发送
数据的缓存的最大值
,单位为 bytes`` 字节,也存在
net.core.rmem_default和
net.core.rmem_min`
net.core.rmem_max
:该参数定义了套接字接收缓冲区
的最大大小。用于存储从网络接收到的数据
,等待应用程序读取。较大的接收缓冲区可以提高网络吞吐量
和应用程序的性能,尤其对于高速网络或大量数据传输
的场景。
net.core.wmem_max
:该参数定义了套接字发送缓冲区
的最大大小。用于存储应用程序要发送到网络的数据,等待发送到网络。较大的发送缓冲区可以提供更好的网络发送性能
,尤其在高负载或延迟网络
环境下。
这组内核参数的优化往往结合 BDP
来调整,等于或者大于 BDP 的值
,关于 BDP,下文我们会讲。
在 通过 ifconfig
查看系统中所有网络设备的基本性能统计信息。
关于部分参数的说明
如果 overruns
存在值,可能需要调整上面的内核参数,适当增大。
TCP 级别内核参数
net.ipv4.tcp_rmem,net.ipv4.tcp_wmem
net.ipv4.tcp_rmem
和 net.ipv4.tcp_wmem
用于配置 TCP 套接字的接收缓冲区和发送缓冲区
的大小
。
net.ipv4.tcp_rmem
:配置 TCP 套接字接收缓冲区的大小。包含三个整数的列表,表示 最小、默认和最大(以字节为单位)
。TCP 接收缓冲区用于存储从网络接收到的数据
,等待应用程序读取。
net.ipv4.tcp_wmem
:配置 TCP 套接字发送缓冲区的大小。同样,也是包含三个整数的列表,表示最小、默认和最大(以字节为单位)。TCP 发送缓冲区用于存储应用程序要发送到网络的数据
,等待发送到网络。
开启一个sokcet
,内核会在 min(第一列)
和 max(第三列)
之间自动设置一个 default(第二列)值
TCP 缓冲区
的大小应根据系统和网络的需求进行调整。较大的缓冲区可以提高网络性能
,特别是在高负载或高延迟
的网络环境中。但是,过大的缓冲区可能会导致内存占用增加或延迟
问题。
这两个参数的调优同样参考 `BDP`` 来进行优化
BDP
可以验证缓存大小
是否合适,如何计算最大吞吐量时需要多少 缓存 呢?
BDP 是什么
round trip time(rtt 往返延迟时间)
本地发送数据包到远程,并从远程返回的时间叫 RTT
!
使用 ping 命令可以查看平均往返延迟时间
Linux
最后一行可以看到,连接百度有 14 ms
的 RTT
时间,最后的输出结果中可以看到结果信息,假设带宽为 千兆带宽,1000Mbps
,即 1Gb/s
,假设我们使用的是 千兆网卡
1Gb/s * 14.522ms
:带宽
乘以往返时间(RTT)
可以用来估算网络传输的往返延迟
(Round-Trip Time Delay)。
将速度单位转换为比特每秒
(b/s):1 Gb/s = 1,000,000,000 b/s
将时间单位转换为秒
:14.522 ms = 14.522 * 0.001 s = 0.014522 s。
。
现在,我们可以计算表达式:1,000,000,000 b/s * 0.014522 s = 14,522,000 b
将比特转换为字节
: 14,522,000 bit = 14,522,000 bit / 8 byte = 1,815,250 byte。(1 字节(byte)等于 8 位 (bit),将 14,52 2,000 比特除以 8 以获得字节数。 因此,结果是 1,815,250 字节。
将字节转换为 KiB(二进制制式的千字节)
,需要除以 1024:
1,815,250字节 / 1024 = 1,772.705 千字节(KiB) / 1024 = 1.731 兆字节(MiB)=1,733.0625兆字节 / 1024 = 0.00169千兆字节(GiB)
那么发送一个数据包等待回应的时间是 0.014522 s
秒,实际上如何没有这个延迟,这个时间段可以发送 1.731 MiB
的数据,这个概念被称为时延带宽乘积(Bandwidth Delay Product,BDP)
互联网的 rtt
值一般会比较大,rtt 值,即往返延迟越低,BDP 的值就越低
。
如果 BDP(时延带宽乘积)大于64KiB(64千字节)
,则在 TCP 连接中建议启用TCP窗口缩放(TCP window scaling)
。TCP 窗口缩放是一种机制,用于扩大TCP连接中的传输窗口大小
,以适应高带宽
和高延迟
的网络环境。
设置 tcp_window_scaling 的值为 1
如果一个系统需要处理多个并发连接
,则每个socket 缓存(rmem、wmem等)
的大小只要可以处理单个socket
的BDP容量
即可。
一般几百KiB
基本够用,但默认的208KiB
有点小!当然缓存区也不是越大越好
过多的缓存数据包
导致了数据包的延迟
,延迟抖动
和降低
了网络的总的通吐量
的现象
对于一个速度很快的网络而言,如果配置一个过大的缓存区,也可能导致及时通讯服务类的应用体验很差。
根据 BPD 配置网络调优参数
下面为在 window 机器上 ping 谷歌 DNS ,可以看到 有 169 ms
的 RTT
假设当前为百兆带宽,计算 BDP :100 Megabits/s * 0.169 s * 1/8 Byte/bits = =100,000,000 bits/s * 0.169 s * 0.125 Byte/bit = 2,112,500 Bytes
添加 TCP 的读取缓存相关内核参数配置
备份当前内核参数
配置调优后的内核参数
修改设置(socket max 最大值等于刚才计算的 BDP 的值,默认值设置为最大值的一半:
碎片缓冲区参数
碎片缓存区
相关内核参数在一些分片重组丢包
的场景需要优化
当前系统的默认参数
net.ipv4.ipfrag_high_thresh
设置了碎片缓冲区的高水位线为 4194304 字节(4 MB)。当碎片缓冲区的使用率超过该阈值时,内核会开始丢弃新到达的碎片。
net.ipv4.ipfrag_low_thresh
设置了碎片缓冲区的低水位线为 3145728 字节(3 MB)。当碎片缓冲区的使用率低于该阈值时,内核会停止丢弃新到达的碎片。
net.ipv4.ipfrag_max_dist
是一个用于限制数据包分片重组的内核参数。它定义了分片偏移(fragment offset)之间的最大允许间隔。当分片之间的偏移超过此阈值时,内核会丢弃分片并阻止重组,以防止可能的攻击和资源耗尽。
net.ipv4.ipfrag_secret_interval
设置了碎片缓冲区的密钥更新间隔为 0,表示不进行密钥更新。
net.ipv4.ipfrag_time
设置了碎片在缓冲区中保持的时间为 30 秒。超过该时间的碎片将被丢弃。
超时
在网络通信过程中,有 601 个碎片在超时后被丢弃了
通常发生在碎片重组过程中,当某个碎片的到达时间超过了一定的时间限制(通常是根据 net.ipv4.ipfrag_time
参数设置的)而没有完全到达时,内核会丢弃这个碎片以避免无限等待。
解决方法:调整超时时间
frag_high_thresh, 分片的内存超过一定阈值会导致系统安全检查丢包
有 8094 个数据包的重组失败了。这通常发生在数据包分片(fragmentation)和重组(reassembly)的过程中。
增加碎片缓冲区
的大小可以提供更多的空间来缓存和重组分片。通过调整 net.ipv4.ipfrag_high_thresh
和 net.ipv4.ipfrag_low_thresh
参数的值来增加缓冲区的大小。
其他网络相关内核参数
常用其他网络相关内核参数(需要修改):
上面的配置修改都是临时操作,内核参数的永久修改需要 写在配置文件 /etc/sysctl.conf
开启巨帧
网络上传输的数据包一般包含:包头和数据载荷,一个典型的 TCP/IP 数据包头会包含以太网头部信息,IP 头部信息和 TCP 头部信息。
有这些报头都包含在网络上使用的最大传输单元(MTU)中,单个数据包的最大大小。
例如,使用 TCP 连接使用 52 个字节的协议头。默认 MTU 为 1500 字节,这几乎占开销损失的总容量的 3.5%。
有一种办法是改变通信协议,比如将 TCP 改为 UDP,头部信息就会从 52 字节变成 28 字节(对于 1500 数据包而言,1.9%的开销),但是 UDP 不一定适合所有业务。另一个方法是增加 MTU 的大小,将 MTU 修改为超过标准的 1500 字节,被称为巨帧(Jumbo Frames)。修改巨帧需要所有硬件设备都支持该功能。
我们可以使用 nmcli 修改网卡的 MTU 大小(下面的例子将 ens33 网卡的 MTU 修改为 9000)
如果需要修改 MTU 大小,则需要先确认以下这些设备是否支持巨帧(但不限于这些设备):
网卡
交换机
路由器
一般官方推荐定义的巨帧 MTU 为 9000bytes(字节),但是也有设备支持更大的帧数据。
加大帧大小的好处在于,减少了网络中数据包的个数,减轻了网络设备处理包头的额外开销(可以显著提升性能)。
但缺点是,巨帧至今没有标准化,如果使用不同的 MTU 可能会导致有些设备不兼容,而传统的以太网 MTU 是所有设备都兼容的。
博文部分内容参考
© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知 :)
<Rh442 授课笔记>
https://zhuanlan.zhihu.com/p/502027581?utm_id=0
© 2018-2023 liruilonger@gmail.com, All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)
版权声明: 本文为 InfoQ 作者【山河已无恙】的原创文章。
原文链接:【http://xie.infoq.cn/article/8456f6ac600c90bc9a3b57819】。
本文遵守【CC BY-NC】协议,转载请保留原文出处及本版权声明。
评论