网络排查案例课
杨胜辉
eBay 资深运维专家,流量系统负责人
22781 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 39 讲
实战三:不用抓包就能做的网络排查篇 (2讲)
网络排查案例课
15
15
1.0x
00:00/00:00
登录|注册

08 | 分段:MTU引发的血案

客户端超时设置
MTU限制导致报文无法通过
丢包或乱序
出现重复确认和重传失败
时延和HTTP处理时间正常
使用iptables规则
为什么重传只有两次?
为什么重传没有成功?
为什么有重复确认 (DupAck)?
经过LB的压测
绕过LB的压测
查看和修改offload特性
Flow graph
需要尽量避免
IP层的分包机制
网卡负责报文拼接
减轻CPU负担,由网卡完成分段
在网络中间环节修改TCP报文的MSS值
调整MTU大小
问题定位
出现大量HTTP报错
客户在公有云上进行软件负载均衡压力测试
抓包示例文件
个人经历中的MTU问题?
修改MSS的劣势或不足?
ethtool
Wireshark
IP分片
GRO (Generic Receive Offload)
TSO (TCP Segmentation Offload)
“暗箱操作”
一般对策
抓包分析
背景
GRO (Generic Receive Offload)
TSO (TCP分段卸载)
MSS (最大分段大小)
MTU (最大传输单元)
IP分片 (Fragmentation)
TCP分段 (Segmentation)
附录
思考题
工具使用
相关技术
解决方案
案例分析
核心概念
MTU问题分析与解决

该思维导图由 AI 生成,仅供参考

你好,我是胜辉。
第 1 讲里,我给你介绍过 TCP segment(TCP 段)作为“部分”,是从“整体”里面切分出来的。这种切分机制在网络设计里面很常见,但同时也容易引起问题。更麻烦的是,这些概念因为看起来都很像,特别容易引起混淆。比如,你可能也听说过下面这些概念:
TCP 分段(segmentation)
IP 分片(fragmentation)
MTU(最大传输单元)
MSS(最大分段大小)
TSO(TCP 分段卸载)
……
所以这节课,我就通过一个案例,来帮助你彻底搞清楚这些概念的联系和区别,这样你以后遇到跟 MTU、MSS、分片、分段等相关的问题的时候,就不会再茫然失措,也不会再张冠李戴了,而是能清晰地知道问题在哪里,并能针对性地搞定它。

案例:重传失败导致应用压测报错

我先来给你介绍下案例背景。
在公有云服务的时候,一个客户对我们公有云的软件负载均衡(LB)进行压力测试,结果遇到了大量报错。要知道,这是一个比较大的客户,这样的压测失败,意味着可能这个大客户要流失,所以我们打起十二分的精神,投入了排查工作。
首先,我们看一下这个客户的压测环境拓扑图:
这里的香港和北京,都是指客户在我们平台上租赁的云计算资源。从香港的客户端机器,发起对北京 LB 上的 VIP 的压力测试,也就是短时间内有成千上万的请求会发送过来,北京 LB 就分发这些请求到后端的那些同时在北京的服务器上。照理说,我们的云 LB 的性能十分出色,承受数十万的连接没有问题。不夸张地说,就算客户端垮了,LB 都能正常工作。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文通过一个案例详细介绍了在公有云服务中,客户对软件负载均衡进行压力测试时遇到的问题。文章首先介绍了压测失败的背景和环境,然后通过抓包分析,分别展示了绕过负载均衡和经过负载均衡的压测过程中的报文情况。在经过负载均衡的压测中发现了大量的重传和重复确认,进一步分析发现是由于客户端未收到服务端的第一个数据报文导致的。最后,文章提到了Wireshark的Flow Graph工具,可以更直观地展示报文的流向,帮助读者更好地理解报文情况。通过这个案例,读者可以深入了解MTU、MSS、分片、分段等概念的联系和区别,以及在网络设计中可能出现的问题和解决方法。文章还介绍了解决MTU引发的问题的一般对策和“暗箱操作”,展示了网络领域的灵活性和可玩性。文章还介绍了TSO和IP分片的概念,以及如何使用ethtool工具查看和控制offload相关特性。通过对比成功和失败两种场景下的不同的抓包文件,能比较快地定位到问题根因。最后,文章提出了两道思考题,引发读者对于网络设计和问题排查的思考。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《网络排查案例课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(28)

  • 最新
  • 精选
  • 江山如画
    问题1: 从可用性角度分析,通过 iptables 修改 mss 只对 tcp 报文生效,对 udp 报文不生效。由于udp 报文传输时没有协商 mss 的过程,如果发现 udp 负载长度比 mtu 大,会交给网络层分片处理,分片传输途中只要有一个分片丢了,由于 udp 没有反馈给发送端具体是哪个分片丢了的能力,只能重新传整个包,传输效率会变低。 从运维角度分析,由于修改中间环节某个服务器的 iptables ,对于其它侧是透明的,可能会对定位问题带来困扰。 问题2: 遇到过 mtu 引发的问题。之前手动创建了虚拟网卡,和物理网卡之间做了流量的桥接,发现有些报文在二者之间转发时会被丢掉,分析发现虚拟网卡的 mtu 设置过大,并且报文 DF 位设置为了 1,通过 ifconfig 命令把虚拟网卡的 mtu 改小,报文就可以正常转发了。

    作者回复: 回答的很详细,很明显经过了仔细的思考,不是随便写的,不光为你的答案,我更要为你的学习态度点赞! udp这部分,协议要求是udp载荷不要超过512字节,比常见MTU小很多,所以可能这个超出MTU的问题没有tcp那样严重。但是就像你说的,udp丢包的话,相应的容错和重传,协议栈本身是不做的,这就给应用程序提出了要求。 从运维角度分析的答案也很好,我也是很看重这一点:如果把配置“藏”在各个地方而其他人不知道,就等于是给其他运维和开发人员“埋雷”,我们应该尽量避免。

    2022-02-07
    4
    20
  • Geek_955506
    Flow Graph 展示页的左下角有一个复选框 "limt to display filter",勾上之后就只展示过滤的内容了,不需要再单独保存展示

    作者回复: 多谢补充,工具的使用方面有很多小的细节:)

    2022-06-05
    9
  • 张靳
    开始对[为什么有重复确认(DupAck)]这个小节标志位Dup ACK的两个报文是载荷为688和57的两个报文的确认报文不是很理解,在杨老师指导下豁然开朗,做一下我的理解记录: 最开始我对wirshark的符号有误解,我选中Dup ACK报文发现是7号报文(三次握手的ack报文)的重复确认(有两个对勾),我就以为是7号报文的确认报文,这个理解本身有问题,因为ack本身没有ack了,不然就没完没了了。查阅了Dup ACK的定义,当发现丢包或者乱序的时候接收方会收到一些Seq序列号比期望值大的包,每收到这种包就会ack一次期望的Seq值。 所以我们知道可能有丢包才会有重复确认,且确认得是对端发过来得报文。那么结合整个tcp流来看,发生重传得报文是没收到的,然后确认了688和57载荷得报文。

    作者回复: 很好,自己想明白了这知识就真的是你的了:)

    2022-02-12
    4
  • 斯蒂芬.赵
    不明白,如果传入的tcp载荷超过了mtu值,不应该根据mss值自动的分段么

    作者回复: 是的,不过这里的麻烦是由于很多网络限制,通信两端其实经常无法收到PMTU ICMP消息,也就导致无法及时调整MSS来适配网络状况,也是文中案例的诱因之一。

    2023-01-11归属地:山东
    2
  • piboye
    包的收发路径不一致的时候, MSS 协商是不是就失效了? 运营商网络, 如果出现链路调整, 之前协商的MSS 是不是也会可能失效了? 特别是长链接场景, 这种情况, 是不是要预先设置一个比较保守的值?

    作者回复: Linux对MSS会随时间发生变化这一点也是有机制来保护的,比如依赖PMTU报文进行调整。PMTU是网络设备会遵循的协议,当设备收到一个超过其MTU的报文时,一方面会丢弃,一方面会返回一个Destination Unreachable的ICMP消息,具体可以参考RFC 1191: https://www.rfc-editor.org/rfc/rfc1191 由于网络的复杂性,这种ICMP消息经常会被拦截,导致发送端压根不知道自己的报文因为MTU超限而被丢弃了,就会导致各种问题。 在已经知道有隧道的情况下,尽量设置合理的相对低的MTU值,是保障网络通信的一个经验。

    2022-08-03归属地:上海
    2
  • Geek3340
    老师,有一点不是很理解: 由于 Tunnel 1 比 Tunnel 2 的封装更大一些,所以服务端选择了不同的传输尺寸,一个是 1388,一个是 1348。 为啥会有这种选择呢,按照理解,MSS会自动从MTU-40来计算,不太理解为啥中间的IPIP隧道会影响到MSS的分段 经过LB的,1388 + 40(TCPIP) + IP(20) + IP(20) = 1468 不经过LB的,1348 + 40(TCPIP) + IP(20) = 1408 在本次案例中,以下命令能解决问题,应该如何理解呢?我理解1400应该是调整小了MSS到1400,但是之前的1388也没有超限呀,不理解: iptables -A FORWARD -p tcp --tcp-flags SYN SYN -j TCPMSS --set-mss 1400

    作者回复: 您好,图中tunnel1也是用在gz和bj服务器之间的,并不是仅仅在gz和bj lb之间。 第二个问题,mss改为1400是一个示例,并不是说当时这个案例就是用了这个数值。 有任何其他疑问也都可以提哈

    2022-02-08
    5
    2
  • 志强
    老师有几个疑问请教: 问题1."我们选中 575 号报文"下边的图中Dup ACK报文是31号,"为什么是两个重复确认报文呢?我们把视线从 2 个 DupAck 报文往上挪"下边的图中dup ack 就变成了3号,是人为修改的还是怎么回事? 问题2.有两次31号报文的dup ack,是因为收到了额外两次17号报文吧,有人肯能会问那为啥看不到17号报文的重传呢,这个我也不太清楚,可能是处理重传的位置在捕获抓包之后吧,要是在客户端抓包就能看到17号报文的重传,请老师指正 问题3.无论是握手的ack 还是数据的ack,这个ack是谁给回的,知道是内核给回复,具体哪一层的什么函数处理过后给回复的ack;kcp老师了解吗,是应用层在再给回复还是也是内核给的恢复 谢谢老师,期待您的详细解答

    作者回复: 关于这3个问题: 1. 你看到DupAck to从#31变成了#3,是因为截图的问题,#3那个是另外单独保存的抓包文件,所以编号不一样,但是TCP流确实是同一个。这个截图我们刚替换成统一#31的,也感谢你的细心! 2. 这两次对#31报文的DupAck,只是因为握手之后的第一个数据报文(也就是1388字节那个)没有到客户端,但后面两个报文到了,所以客户端回复的两次ack号只能停留在握手结束的时候。这不是说客户端收到了两次SYN+ACK。DupAck的意思是:“我需要你那边跟这个ack号等值的seq号的报文”,而不是“我需要你再发一次我刚刚ack过的报文”,这里正好差了一个“身位”,你再想想? 3. ack是内核协议栈回复的,你可以从github上git clone一下linux内核代码,然后在IDE里,搜一下TCPHDR_ACK在代码中的位置。大体上说,ACK标志位的设置是一类函数,比如SYN、FIN、RST(不含被动RST)、传输阶段等报文都是在各自不同的函数里面设置了ACK标志位,而它们的发送都会走到tcp_transmit_skb()来完成。 kcp没了解,也没用过:(

    2022-02-08
    3
    2
  • 潘政宇
    杨老师,中间设备不是只是转发作用吗,协商mss也参与吗

    作者回复: 中间设备负责转发,但因为IP和TCP报文是不加密的,所以可以在中间环节修改这些转发报文的MSS字段,这就起到了让通信两端都按照修改后的MSS进行传输的效果。 理论上说,不光MSS,几乎其他任何IP头部和TCP头部字段都可以被中间设备修改。

    2022-02-07
    2
    2
  • Dexter
    TCP分段的计算公司,那个IP header length和TCP header length是如何的得知的?难道都是按照默认的IP HDR =20, TCP HDR =20吗?这不是很可靠吧。 还有TCP segmentation probe功能开启是不是能够解决案例中的问题? [root@master03 ipv4]# cat tcp_mtu_probing 0 [root@master03 ipv4]# 问题2:如果启用了TSO或者GRO,为什么经常在抓包中看到TCP segment还是1460? 问题3: LRO是什么?老师能帮忙解答下吗?

    作者回复: 您好~ 1. 你问的是RFC879里面的这个公式吗?SndMaxSegSiz = MIN((MTU - sizeof(TCPHDR) - sizeof(IPHDR)), MSS) 。MSS是每个TCP连接各自维护的,所以是根据这条连接的实际情况来决定大小。比如在握手阶段,已经确定要使用TCP option的timestamp,那么这里的TCPHDR就不再是20字节了,而是更大,得出的MSS就更小。 mtu_probing没有在这个案例里使用,遗憾的是现场早就没有了,要不然可以试试。 2. 启用了TSO或者GRO,还是看到1460?这我倒没注意,一般启用以后,常见的是2920、2800或者更大的值。你依然看到1460,有一个可能性是网卡并没有严格去执行offload。 3. LRO是Large Receive Offload,跟GRO类似。LRO/GRO启用后,tcpdump抓取到的接收方向的报文就是合并过的。

    2022-02-26
    1
  • Dexter
    iptables -A FORWARD -p tcp --tcp-flags SYN SYN -j TCPMSS --set-mss 1400 --- 文中说是在nat表,不过这个command没有指定nat表,而且nat表中应该没有forward chain

    作者回复: 嗯这里有误,我更正一下,是默认(没有指定-t)的filter表,谢谢:)

    2022-02-26
    1
收起评论
显示
设置
留言
28
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部