问题描述
终端设备向云端POST数据,数据量较小的没有问题,数据量大的必然出现丢包。网络很通畅,延迟较低。
分析
后来发现,终端到云端的通信路径上某个路由器节点的MTU小于终端的MTU,当终端发出的IP数据包长度大于该路由器节点的MTU时,IP数据包被丢弃。
处理方法
降低终端(Linux系统)的MTU。这里包含两个问题:
- 如何设置MTU?
- MTU设置为多少?
如何设置MTU?
什么是MTU?
MTU: MTU( Maximum Transmission Unit),最大传输单元,单位是字节。
大部分的网络设备的mtu默认值是1500。如果本机的mtu值大于网关的mtu值,大的数据包就会被拆开来传送,这样会产生数据包的碎片,增加丢包率,降低网络速度。把mtu设置比网关小或者相同,可以减少丢包。设置合适的mtu值,可以减少部分网站打不开,上网速度慢等问题。一般情况,可以把路由器、交换机和服务器的mtu值统一设置。
查看服务器的mtu值
cat /sys/class/net/网口名称/mtu
或者
# ifconfig
ens18: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1200
临时修改mtu值:(重启服务器后失效)
ifconfig <网口名称> mtu 1200
永久生效
在NetworkManager的连接配置文件里配置mtu,在[ethernet]选项添加一行 mtu=1280:
MTU设置为多少?
MTU设置为多少比较合理?可以设置为PMTU的值。
PMTU是什么?
PMTU是Path MTU(Maximum Transmission Unit)的缩写,指的是在网络通信中,从源主机到目的主机所经过的所有网络设备中,能够通过的最大数据包大小。PMTU的原理是通过不断发送大小不同的数据包,直到发现一个最大的数据包能够成功传输,从而确定PMTU的大小。
PMTU的应用主要是在TCP/IP协议中,用于避免IP分片。当一个数据包的大小超过了某个网络设备的MTU时,该设备会将数据包分片,然后再将分片后的数据包发送出去。这样会增加网络传输的负担,降低网络传输的效率。因此,TCP/IP协议中的PMTU发现机制可以帮助避免IP分片,提高网络传输的效率。
怎么检测PMTU?
可以使用ping命令来检测。
PMTU最初是为IPv4路由器设计的。可以使用ICMP协议中的type和code字段发送MTU=XXX的消息,当这个ICMP消息到达IP包的源主机时,源主机将设置正确的MTU。
可以使用ping命令来检测PMTU,例如:
ping -c 4 -M do -s 1472 <IPv4 Address>
其中,-c 指定ping的次数。
-M <pmtud opt> define mtu discovery, can be one of <do|dont|want>
Select Path MTU Discovery strategy. pmtudisc_option may be
either
do (prohibit fragmentation, even local one),
want (do PMTU discovery, fragment locally when packet size is large),
or
dont (do not set DF flag).
-M do
表示在传输过程中,IP数据包禁止分包,如果路由器收到长度比自身设置的MTU大的IP数据包,则不能拆分,只能丢弃,并在ICMP回复报文中设置MTU大小。
-s 1472
表示设置ICMP的PDU(有效载荷)为1472字节。ping 使用的是ICMP协议,ICMP的下层协议是IP协议,ICMP首部(header)共8字节,IP首部(header)共20字节,ICMP的IP数据包 = IP首部 + ICMP首部 + ICMP的PDU,所以 -s 1472 表示 整个IP数据包的长度等于20+8+1472 = 1500 字节。
如果源主机到目的主机的通信路径中有节点的MTU小于1500,则会返回ICMP消息“message too long”到达IP包的源主机:
# ping -c 4 -M do -s 1472 x.x.x.x
PING x.x.x.x (x.x.x.x) 1472(1500) bytes of data.
ping: local error: message too long, mtu=1492
ping: local error: message too long, mtu=1492
ping: local error: message too long, mtu=1492
ping: local error: message too long, mtu=1492
--- 123.103.127.118 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3051ms
推荐的MTU值是1492,去掉ICMP首部(header)的8字节和IP首部(header)的20字节,1492 - 28 = 1464,-s 的值修改为1464试试:
# ping -c 4 -M do -s 1464 x.x.x.x
PING x.x.x.x (x.x.x.x) 1464(1492) bytes of data.
1472 bytes from x.x.x.x: icmp_seq=1 ttl=49 time=20.2 ms
1472 bytes from x.x.x.x: icmp_seq=2 ttl=49 time=20.4 ms
1472 bytes from x.x.x.x: icmp_seq=3 ttl=49 time=20.6 ms
1472 bytes from x.x.x.x: icmp_seq=4 ttl=49 time=20.4 ms
--- 123.103.127.118 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 20.241/20.402/20.563/0.114 ms
将源主机的MTU值修改为1492后,问题解决。
如果仍返回“message too long”,可以逐步降低-s 的值,直至ping返回成功。