pub struct MtuDiscoveryConfig { /* private fields */ }展开描述
控制 MTU 探测的各个参数。
§为什么要做 MTU 探测
QUIC 在设计上有意保证:在握手阶段,客户端与服务器之间的网络路径能够传输有效载荷为 1200 字节且不分片的 UDP 数据包。换句话说,连接建立后我们就知道该路径的最大传输单元(MTU)至少为 1200 字节(再加上 IP 与 UDP 头部)。因此,QUIC 端点可以放心地把待发数据切成 1200 字节的数据包(如果端点发送更大的包,可能会因过大而被丢弃)。
然而,发送数据包本身会带来显著的开销。如果同样一份信息能用更少的包发完,就能获得更高的吞吐。所需发送的数据包数量与 MTU 成反比:MTU 越大,单包可承载的字节越多,传输给定数据量所需的包数也就越少。
大多数网络的 MTU 都大于 1200 字节。通过 MTU 探测,端点可以探知路径的 MTU;若发现 MTU 更大,便可开始发送更大的数据包。
§MTU 探测的实现细节
Quinn 通过 DPLPMTUD(Datagram Packetization Layer Path MTU Discovery)实现 MTU 探测,详见 RFC 9000 第 14.3 节。该方法会发送填充到特定大小的 QUIC 数据包(称为 PMTU probe),然后观察对端是否回应 ACK。如果收到 ACK,则说明该探测包成功到达对端,也即该路径的 MTU 至少为该包的大小。如果探测包丢失,会再重发 2 次;3 次都失败时,便认定该路径的 MTU 小于该包的大小。
MTU 探测按一定周期运行(默认每 600 秒一次),该周期通过 MtuDiscoveryConfig::interval 指定。第一次探测发生在握手刚结束后;后续探测的调度起点是上一次探测完成的时间,到达 interval 之后再次运行。
由于 MTU 的搜索空间非常大(最小为 1200,最大为 65527),Quinn 采用二分查找以尽量减少探测次数。首次探测时,搜索下界为 TransportConfig::initial_mtu;后续探测时,下界为当前已探测到的 MTU。上界则取 MtuDiscoveryConfig::upper_bound 与握手阶段从对端收到的 max_udp_payload_size 传输参数中的较小者。
§黑洞检测
如果在某个时刻网络路径不再接受探测到的那个尺寸的数据包,那么丢包最终会触发黑洞检测,并将探测到的 MTU 重置为 1200。此时将等待 MtuDiscoveryConfig::black_hole_cooldown 时间后再次触发 MTU 探测(忽略原先基于 MtuDiscoveryConfig::interval 设置的定时器)。
§对端之间的相互作用
A 到 B 的路径 MTU 与 B 到 A 的路径 MTU 不一定相同。因此,连接中的每个对端都需要独立地运行 MTU 探测,才能发现各自方向的路径 MTU。
实现§
源代码§impl MtuDiscoveryConfig
impl MtuDiscoveryConfig
源代码pub fn interval(&mut self, value: Duration) -> &mut MtuDiscoveryConfig
pub fn interval(&mut self, value: Duration) -> &mut MtuDiscoveryConfig
指定在完成 MTU 探测之后,需等待多长时间才会开启新一轮 MTU 探测。
默认为 600 秒,符合 RFC 8899 的建议。
源代码pub fn upper_bound(&mut self, value: u16) -> &mut MtuDiscoveryConfig
pub fn upper_bound(&mut self, value: u16) -> &mut MtuDiscoveryConfig
指定 MTU 探测所搜索的最大 UDP 有效负载大小的上限。
默认为 1452,以保证在使用 IPv4 与 IPv6 时不超过以太网的 MTU。允许的最大值为 65527,对应 IPv6 上允许的最大 UDP 有效负载。
无论实际网络路径的 MTU 如何,使用一个任意大的上限都是安全的,唯一的代价是 MTU 探测可能需要更长时间才能完成。
源代码pub fn black_hole_cooldown(
&mut self,
value: Duration,
) -> &mut MtuDiscoveryConfig
pub fn black_hole_cooldown( &mut self, value: Duration, ) -> &mut MtuDiscoveryConfig
指定在检测到“黑洞”之后,MTU 探测需等待多长时间才会再次运行。默认为一分钟。
在发生拥塞时,黑洞检测可能被误触发,因此在一段较短时间后再次尝试 MTU 探测是合理的。
源代码pub fn minimum_change(&mut self, value: u16) -> &mut MtuDiscoveryConfig
pub fn minimum_change(&mut self, value: u16) -> &mut MtuDiscoveryConfig
指定用以终止 MTU 探测阶段的最小 MTU 变化量。默认为 20。
trait 实现§
源代码§impl Clone for MtuDiscoveryConfig
impl Clone for MtuDiscoveryConfig
源代码§fn clone(&self) -> MtuDiscoveryConfig
fn clone(&self) -> MtuDiscoveryConfig
1.0.0 · 源代码§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. 更多信息