服务器入坑指北:MTU 与分片的取舍

举报
Tulpartner 发表于 2026/11/05 08:53:18 2026/11/05
【摘要】 小包通、大包不通:ping 能通,一传文件就断;有一个方向的连接能建起来,却传不了数据;把"改小 MTU"当成万能药,改完有些通了、有些还是不通。 顺序是:先把载荷上限算出来 → 再用"禁止分片"的探针找到分界点 → 分清是分片问题还是路径 MTU 发现失效 → 最后才决定改哪一层。

小包通、大包不通:ping 能通,一传文件就断;有一个方向的连接能建起来,却传不了数据;把"改小 MTU"当成万能药,改完有些通了、有些还是不通。
顺序是:先把载荷上限算出来 → 再用"禁止分片"的探针找到分界点 → 分清是分片问题还是路径 MTU 发现失效 → 最后才决定改哪一层。
这篇给三段可直接粘贴的内容:第一段只读(量与现读)、第二段只读(探针定界)、第三段含写操作(改 MTU 与相关开关,标回滚点)。这里的量关系全部可演算,来源是协议规范而不是经验。取值用占位符,命令名、参数名与常量照写。

载荷上限是算出来的,不是试出来的

载荷上限 = MTU - IP 头 - 传输层头。
三个数记住,就能把"探针该用多大"变成算术:

  • 1500 - 20 - 20 = 1460:IPv4 报头是固定 20 字节(不含选项),TCP 报头最小也是 20 字节——所以这是以太网 MTU 下的 TCP 载荷上限(也就是常说的 MSS);
  • 1500 - 40 - 20 = 1440:IPv6 基本报头固定 40 字节,TCP 仍是 20 字节——同样 1500 的链路上,IPv6 每包比 IPv4 少 20 字节;
  • 1500 - 20 - 8 = 1472:ICMP 回显报头只有 8 字节——所以回显探针能填到 1472。
    这三个减项分别是什么头:20 是 IPv4 固定头、40 是 IPv6 固定头、20 是 TCP 最小头、8 是 ICMP 回显头。都取最小值——因为选项会再占空间,取最小值得到的是上限。
    判据:探针大小与 TCP 载荷不是一回事(一个按 8 字节头算,一个按 20 字节头算)——忘记这一点,就会拿 1472 去解释 TCP 的传输失败。

量与现读块

ip link show <接口>                             # 现读本端接口的 MTU
ip route get <目标>                             # 看这个目标走哪条路、出口是哪个接口
sysctl net.ipv4.ip_no_pmtu_disc                 # 现读:非 0 即关闭了路径 MTU 发现
nstat -s                                        # 读"超限丢弃"一类计数:是否真有包因为太大被丢
tracepath <目标>                                 # 现探路径 MTU 与每一跳的值

判据:本端 MTU 只是"这一跳"的量,路径 MTU 是整条路上最小的那一跳——两者不一定相等;nstat 里"超限丢弃"的计数在涨,才说明确实有包因为太大被丢,而不是被别的原因拦掉。

片数怎么算

当载荷超过链路 MTU 时,包会被分片;分片偏移字段(fragment offset)以 8 字节为单位记录,因此每个分片(最后一片除外)的载荷长度必须是 8 的倍数:
片数 = 总长 / 每片载荷,向上取整。
算一遍:总长 3000 字节、每片载荷 1480 字节(这个数能被 8 整除:1480 = 8 × 185):

  • 3000 / 1480 = 2.027…,向上取整 → 3 片;
  • 三片对账:1480 + 1480 + 40 = 3000 ✓ 正好补齐;
  • 若每片载荷取 1500 / 1480 之外的数,注意后面的片要重新算——不是整除时,最后一片会更小。
    判据:偏移不是 8 的倍数就会被拒——所以"每片塞多少"不能随手定。

探针定界块

ping -M do -s <字节数> <目标>                    # 禁止分片:成功/失败的分界点就是路径 MTU
ping -M dont -s <字节数> <目标>                  # 允许分片:对照组

从大往小试(先试 1472 这类上限,再往下):

  • ping -M do -s 1472 <目标> 成功、ping -M do -s 1473 <目标> 失败 → 分界点在这里;路径 MTU = 1472 + 20 + 8 = 1500(回显载荷加 IPv4 头与 ICMP 头);
  • 两个方向的去与回可能不同,所以要各测一次;
  • 同一大小、允许分片就通、禁止分片不通 ⇒ 这就把问题定在 MTU 上:-M dont 是对照组。
    为什么"禁止分片"的包会被丢:IPv4 报头里有一个 DF(禁止分片)位;置了它的包若超过链路 MTU,会被丢弃,并由中间设备回一条 fragmentation needed(需要分片) 的不可达通知——这就是"小包通、大包不通"的机制来源。

两种故障要分开

现象 结论 怎么判
只有大包不通,且没有任何回执 路径 MTU 发现失效(那类通知被拦掉了) 换一条路径试:换路径就好 → 是这条链路上的通知被拦
在同一条链路上稳定复现 链路 MTU 配错(本端或对端) 换路径照旧 → 是端点的配置问题
判据:换一条路径试——这一条动作就能把两类故障分开。相关的取值语义:net.ipv4.ip_no_pmtu_disc 非 0 即关闭路径 MTU 发现;net.ipv4.tcp_mtu_probing 的取值语义是 0 关闭 / 1 检测到"黑洞"才开 / 2 始终开(以现读为准);若你的内核提供 net.ipv4.mtu_expires,它表达探到的路径 MTU 缓存多久——较新内核上可能已无此项,以现读为准;net.ipv4.tcp_base_mss 是探测的起始段长(与探测配套)。

改与读回块

在你动手改 MTU 之前,先把这条代价看清:改小 MTU 是用吞吐换连通——每一包里头的头占比上升,同样数据量需要更多的包,这是取舍,不是免费的修复。优先修"通知被拦",而不是把 MTU 一律改小。

ip link show <接口>                             # 改前:记录原值(回滚依据)
ip link set <接口> mtu <字节数>                  # 改本端 MTU(高风险写操作,需回滚点)
ping -M do -s <字节数> <目标>                    # 读回:新的分界点在哪里
nstat -s                                        # 读回:超限丢弃计数还在不在涨

读回是独立的一步,不许省:改完要回跑探针确认新的分界点,并复核吞吐相关的计数——"通是通了、吞吐掉了"必须看得见。改 MTU 与改相关内核开关都属高风险写操作,需回滚点。

现象到动作的判定表

现象 结论 动作
小包通、大包不通 大小相关,不是随机丢 用 ping -M do -s <字节数> <目标> 从大往小找分界点
允许分片就通、禁止分片不通 问题在 MTU 上 记录该分界点,算回路径 MTU
换路径就好 路径 MTU 发现这条链的问题 查 DF 那类通知为什么被拦,而不是先改 MTU
换路径照旧 端点配置问题 核对本端与对端的 MTU
改小 MTU 后通了但吞吐下降 用吞吐换了连通 记下这个代价,评估是否还有更划算的修法

改完怎么验证:每项一条判据

  • 探针的分界点等于预期的路径 MTU;
  • 两个方向各测一次;
  • 允许与禁止分片两个对照的结论一致;
  • 超限丢弃计数不再增长;
  • 有回滚形态与原值记录。

这篇不解决什么

  • 讲端口冲突与监听地址的边界的那篇是听没听、听在哪;本篇是包能不能过去——两篇都在"连不上"这一大类里,但层不同。
  • 讲网卡中断与软中断分布的那篇是收包的核间分布;本篇是包的大小与分片。
  • 讲连接跟踪表满了会怎样的那篇是连接状态表打满;本篇不涉及状态表。

踩坑清单

  • 把"大包不通"一律归为 MTU:先分清是丢还是被拒。
  • 只测一个方向:去与回可能是两条路径。
  • 只改本端不看对端:两头的 MTU 都要核对。
  • 拿经验值当上限:该算——MTU - 头。
  • 忘记 ICMP 的头是 8 字节:探针大小与 TCP 载荷不是一回事。
  • 分片偏移不是 8 的倍数:那样会被直接拒掉。
  • 把"一律改小 MTU"当修复:吞吐代价没算。
  • 只看"通不通"不看超限计数:不知道有没有真丢。
  • 改完不换路径复核:两类故障分不开。
  • 不知道 DF 位的作用:看到"需要分片"的通知也不知道它在说什么。
  • 忽略 net.ipv4.ip_no_pmtu_disc 的现读值:它是 0 还是非 0,结论完全不同。
  • 把路径 MTU 缓存当永久有效:缓存有有效期,**而且能不能调、叫什么名字都随内核版本不同,
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。