3、MTU与TLS记录层分片:MTU发现机制、TLS记录层分片策略、IP分片与TLS分片的权衡
聊到TLS性能,MTU这个话题是绕不开的。很多人觉得MTU是网络层的事,跟TLS有什么关系?其实关系大了去了。我见过不少生产环境,就因为MTU配置不当,TLS握手慢得像蜗牛,数据传输还频繁超时。
说白了,MTU决定了你的数据包能装多少东西。TLS记录层如果不管这个限制,数据到了IP层就会被拆成碎片。碎片多了,丢包概率就上去了,性能自然就崩了。
3.1 PMTUD:路径MTU发现机制
PMTUD(Path MTU Discovery)是IP层的一个机制。它的目标很简单:找到整条链路上最小的MTU。你想想看,数据包从你的服务器到客户端,中间要经过多少路由器?每个路由器都有自己的MTU限制。只要有一个环节的MTU比你的包小,包就会被丢弃或者分片。
PMTUD的工作原理是这样的:
- 发送端在IP头里设置DF(Don't Fragment)标志,告诉路由器别分片
- 如果某个路由器发现包太大,就丢包,并返回ICMP消息"需要分片但DF已设置"
- 发送端收到ICMP后,减小包大小,重新发送
- 重复这个过程,直到找到能顺利通过的最小MTU
听起来挺完美对吧?但实际坑很多。我记得有一次排查一个跨国链路的TLS性能问题,发现客户端一直收不到ICMP消息。为什么?因为很多云厂商和运营商为了安全,直接把ICMP给过滤了。PMTUD在这种情况下就彻底失效了。
3.2 TLS记录层分片策略
TLS记录层有自己的分片机制。它把应用层数据切成一个个记录(Record),每个记录最大16KB。但16KB这个值,在大多数网络环境下都太大了。以太网的MTU通常是1500字节,减去IP头和TCP头,实际能用的载荷也就1460字节左右。
所以TLS记录层需要主动分片,把大记录切成小块。分片策略一般有这几种:
| 策略 | 描述 | 适用场景 |
|---|---|---|
| 固定大小分片 | 每个TLS记录固定为1400字节左右 | 通用场景,简单可靠 |
| 动态分片 | 根据PMTUD结果动态调整分片大小 | 需要最大化吞吐的场景 |
| 延迟分片 | 等待应用层数据积累到一定量再分片 | 批量数据传输,减少TLS记录头开销 |
我个人习惯用动态分片。虽然实现复杂一点,但能充分利用网络带宽。比如在数据中心内部,MTU可能达到9000字节(巨型帧),这时候用固定1400字节的分片就太浪费了。
3.3 IP分片与TLS分片的权衡
这里有个关键问题:分片到底该在TLS层做,还是交给IP层做?
我的建议是:尽量在TLS层完成分片。为什么?
- IP分片不可靠:IP层分片后,只要一个碎片丢了,整个数据包都得重传。TCP虽然会重传,但效率极低。
- TLS分片可控:TLS记录层分片后,每个分片都是独立的TLS记录。丢了其中一个,只需要重传那个记录,其他记录不受影响。
- 安全考虑:IP分片可能被用于攻击,比如碎片重叠攻击。TLS分片在加密层内完成,安全性更高。
但也不是说IP分片一无是处。在某些极端情况下,比如TLS记录已经加密且无法重新分片时,IP分片就成了唯一选择。不过这种情况很少见。
- TLS分片粒度更细,重传代价更低
- IP分片粒度粗,但实现简单
- TLS分片能避免IP分片带来的安全风险
- IP分片在PMTUD失效时是最后的保底方案
下面这张图展示了TLS分片和IP分片的协作关系:
从这张图可以看出,TLS分片发生在加密之后、TCP传输之前。每个分片都是独立的TLS记录,有自己的序列号。这样即使某个分片丢了,也只需要重传那个分片,其他分片不受影响。
而IP分片发生在IP层,是最后一道防线。如果TLS分片大小超过了路径MTU,IP层才会进行二次分片。但这种情况应该尽量避免,因为IP分片没有序列号,丢了任何一个碎片,整个IP包都得重传。
- 优先在TLS层完成分片,分片大小参考路径MTU
- 启用PMTUD,但要做好ICMP被过滤的预案
- 如果PMTUD不可用,手动设置MSS为1460字节(以太网场景)
- 避免IP分片,除非TLS记录已经无法重新分片
嗯,这里要注意一点:TLS 1.3的记录层最大长度是2^14字节(16KB),但实际使用中,我建议根据网络环境动态调整。比如在WiFi环境下,MTU可能只有1400字节左右,这时候TLS分片设到1300字节比较安全。
我曾经在一个CDN项目中遇到过这样的问题:源站到边缘节点的链路MTU是9000,但边缘节点到客户端是1500。源站用了巨型帧,TLS分片设到了8000字节。结果到了边缘节点,IP层不得不把8000字节的包拆成6个碎片。客户端网络稍微有点波动,碎片就丢了,整个包重传,性能惨不忍睹。
解决方案其实很简单:在边缘节点做TLS卸载,重新分片成适合客户端网络的大小。但这需要硬件支持,不是所有场景都能做到。
所以我的建议是:宁可在TLS层多分几次片,也别让IP层去分片。TLS分片的代价是增加了一些记录头开销(每个分片5字节的TLS记录头),但换来的是更可靠的传输和更低的丢包重传代价。这笔账,怎么算都划算。