佘山网站建设,免费印章在线制作,施工企业发展的建议,唐河网站制作公司TCP 对 RTO 有个最小值限制#xff0c;一般限制为 MIN_RTO 200ms。之所以有这个限制#xff0c;在于要适应 Delay ACK#xff0c;而 Delay ACK 的意义#xff0c;不多说#xff0c;摘自 RFC1122#xff1a; MIN_RTO 应该足够大#xff0c;以覆盖 Delay ACK 的影响一般限制为 MIN_RTO 200ms。之所以有这个限制在于要适应 Delay ACK而 Delay ACK 的意义不多说摘自 RFC1122 MIN_RTO 应该足够大以覆盖 Delay ACK 的影响如果 RTO 过小将导致过多不必要的超时重传。但又不能过大否则将导致超时重传不及时。
这个限制在广域网不存在什么问题。广域网 RTT 一般为几十 ms 量级200ms 的最小超时时间没有任何问题。但当 TCP 运行在数据中心时200ms 超时时间是一段相当漫长的等待。50us 是典型的 DC 网络 RTT4000 倍于 RTT 的等待是不合理的。但又不能在 sender 轻易取消 MIN_RTO 的限制。
DC 内部RTO 有 MIN 限制sender 超时重传不及时取消了该限制万一碰到真的 Delay ACK又会频繁虚假超时TLP 只能解决尾丢的部分问题一旦 RTO 兜底还是会进入漫长等待。取消限制也不是不取消限制也不是。 在所有 receiver 端取消 Delay ACK 是几乎不可能的要么就在 sender 识别 Delayed ACKLinux TCP 已经有了一种方式
if (pkts_acked 1 last_in_flight tp-mss_cache last_in_flight !prior_sacked fully_acked sack-rate-prior_delivered 1 tp-delivered !(flag (FLAG_CA_ALERT | FLAG_SYN_ACKED))) {/* Conservatively mark a delayed ACK. Its typically* from a lone runt packet over the round trip to* a receiver w/o out-of-order or CE events.*/flag | FLAG_ACK_MAYBE_DELAYED;
}但即使识别到了Linux TCP 也没有用这个 flag bit 做更多的事因为有很多规范要遵守。但如果遵守这些规范就注定要在 Delay ACK 和 RTO 的纷乱复杂的关联中纠缠。
本质在于根据 Delay ACK 计算得到 1/8 rtt sample 以及 4*rttvar 已成了噪声正常的做法在计算 RTT 时应该排除掉它们或至少限制它们而不是限制 RTO。
为此我建议一种更准确的 RTT 计算方法以及 RTO 的行为。
首先我们换一种方式获取样本
依上图解释若要排除 Delay ACK 的影响只有 ca_rtt 是唯一有效的样本但当前 Linux TCP 却采用 seq_rtt这里的逻辑要修改。同时因为捎带 ACK 的主机时延不确定要把捎带 ACK 排除掉如果双向传输我这个方法会导致 RTT 样本过少。
假设单向传输(绝大多数场景)以 ca_rtt 作为样本计算 RTT 和 RTO取消 MIN_RTO 限制算出来多少就是多少注意RTO 已经是 us 精度(在实现上可能会消耗过多 CPU 资源具体尚未测试)
if (seq_rtt ca_rtt 40ms || MAYBE_DELAYED)drop sample return
else if (PUREACK seq_rtt ca_rtt)take ca_rtt
else if (SACK)take ca_rtt
else if 捎带ACKdrop samplereturn
else?(可能还有一些没考虑到的...)rtt 7/8*rtt 1/8*ca_rtt
rttvar 3/4*rttvar 1/4*|rtt - ca_rtt|
rto rtt 4*rttvar其实双向传输也无所谓照样可以舍弃 Delayed ACK 以及捎带 ACK 带来的样本因为它们带来的是噪声如果觉得丢掉它们造成样本过少而心里不舒服(其实还是以为违背了标准实现和 Linux TCP 实现不一样而导致心里不舒服…)那么换个视角宁缺毋滥
RTO 的动作需要分两个部分算法如下
if inflight 2*mssreset_timer(RTO_MIN - rto) // 可能真的发生了 Delay ACK回退到原本
elselost_retransmit 至于对 cc 的影响我认为没有影响cc 本来就使用排除了主机时延的 ca_rtt 样本测量网络时延。
圆环闭合了既解决了 RTO 重传不及时问题又解决了真遇到 Delay ACK 但 RTO 过小导致的虚假超时问题。
这个 RTT/RTO 算法能否在 DC 网络上线不是取决于它有多自洽而要基于 DC 网络 TCP 传输的统计特征。receiver 发送了多少 Delayed ACKsender 预判了多少 Delayed ACK如果这两个值均足够大且比值接近 1就直接采用上述算法若 receiver 稀有发送 Delay ACK同时 sender 也鲜有收到 Delay ACK则可直接去除 MIN_RTT 限制大不了就虚假超时频度不高影响就不大相比增加逻辑复杂性直接去掉限制更划算。
下面是一个简单的采集脚本Python 简单分析下即可得统计特征或者肉眼看也行
#!/usr/local/bin/bpftrace#include net/sock.h
#include linux/tcp.hkprobe:tcp_ack_update_rtt
{$tcps (struct tcp_sock *)arg0;if ($tcps-srtt_us3 500) {}else if (arg2 arg4) {printf(normal: %d %d srtt:%d\n, arg2, arg4, $tcps-srtt_us3)}else if ($tcps-srtt_us 0) {}else if (arg2 1000) {}else if (arg2 -1) {}else if (arg3 ! -1) {}else if (arg1 0x10000) {printf(delay: this:%d %d %d srtt:%d\n, arg2, arg4, arg3, $tcps-srtt_us3);} else{printf( %d %d srtt:%d\n, arg2, arg4, $tcps-srtt_us3)}
}根据实际数据样本的统计特征做决策比规划一个自洽闭环的算法更高尚。
TCP 的多个 timer 为网络不确定性提供弹性容错空间而 DC 网络相比广域网有两个明显不同DC 网络时延不确定性更低DC 低时延网络使时延抖动更容易被放大。要针对这两个差异改造 DC 网络 TCP。
试想 RTT 50ms 的广域网连接发生了拥塞后徒增排队时延 20ms抖动为 0.4但在 DC 网络RTT 50us 的连接同样徒增排队时延 20ms抖动就是 400。
如何修改 TCP 以适配这种表观差异简单说就两点压缩动态范围排除固定时延。
首先要压缩弹性空间使 RTO 的操作精度与 DC 网络的 RTT 精度同量级从而可识别抖动因此需要将 RTO 改为 us 级别。其次尽可能消除除传播时延以外的其它时延如 Delay ACK 时延捎带 ACK 时延这些时延取决于主机而非网络在 DC 内这些主机时延在整个 RTT 中占比很大因此 ca_rtt 是更优秀的样本。
更进一步在 DC 内网这特定场景我想能统一重传触发了不再区分 RTOFast RetransmitTLP全归于 RACK。当然广域网也可以只是没有 DC 内网这么迫切需要现有 RTO Fast Retransmit 工作得足够好。
针对 RACK评述几句。
TCP 的 sender 以发送时间序对报文编号receiver 对报文编号确认才合理而非 sender 以字节流序列编号receiver 对字节流序号确认。现实的 TCP 采用了后面不合理的方式导致了不少麻烦。这个已经说了不止一遍。
RACK 对此尽力做了修正。
RACK 在 sender 端维护了一个按照发送时间序排序的队列但它没对报文编号因为没地方可编号所以 receiver 自然没法针对编号进行确认。但至少 sender 有了一个发送时间序该时间序将原始报文和重传报文都包含在内。
虽然 RACK 依旧无法区分 ACK/SACK 对针对谁的但也只是影响 RTT 采样精度至少 RACK 可以做到平滑重传而不是像 dupthresh 那样只有一次重传机会。因此RACK 可以作为一切重传的触发机制而不仅仅应用于 fast retransmit包括不限于 RTOTLP。
甩开 Delay ACK 这个不确定时间后就再也没有 RTO 过大问题TLP 不再需要以 RTO 界定的 “未来” 时间作为 RACK timer 的超时时间便可对尾部传输做统一的安排逻辑反而更简单。当然RTO 的概念还是存在的。
你看若不是 Delay ACKTCP 超时重传多么直白。
当然本文只是我的一个方法该方法是单边方案实现起来相对简单十几行代码搞得定。Google 有一种更正式且中规中矩的方法参见TCP Options for Low Latency。
浙江温州皮鞋湿下雨进水不会胖。