Skip to content

Recovery Policy

b23r0 edited this page Oct 12, 2026 · 2 revisions

English · 简体中文

恢复策略

恢复策略从 1.2.0 起提供,已包含在发布的 1.4.0 中;1.1.0 没有这些接口。它只改变本地恢复调度,不改变 RakNet 报文格式和交付保证,独立于发送策略,默认关闭。

启用和应用位置

[dependencies]
rust-raknet = { version = "1.4.0", features = ["recovery-policy"] }

本地开发可使用任务专属源码副本和 path 依赖。

use rust_raknet::{RaknetSocket, RecoveryOptions};
use std::time::Duration;

async fn configure(socket: &RaknetSocket) -> rust_raknet::error::Result<()> {
    socket.set_recovery_options(RecoveryOptions {
        tail_probe_min_delay: Some(Duration::from_millis(10)),
        ..RecoveryOptions::default()
    }).await?;
    Ok(())
}

在 connect 或 accept 后、启动发送任务前调用。配置作用于单连接 socket,不是监听器构建选项;每个 accept 得到的连接都需要分别设置。代理前端和上游是独立连接,应分别配置需要该策略的发送方向;本端设置不会与对端协商或改变对端配置。socket.recovery_options().await 返回请求的设置,已关闭连接的 setter 返回 ConnectionClosed。

全部恢复参数

字段 默认值 作用 取舍
deadline_driven: bool false 按最早可靠重试期限唤醒,减少期限到达后等待固定维护周期的时间 不降低基础 RTO;更精确的调度仍可能影响负载下的吞吐和延迟
tail_probe_min_delay: Option<Duration> None 允许提前重放一个符合条件的完整尾部数据报,同时启用按期限维护 缩短部分孤立丢包等待,不保证提高吞吐或改善拥塞
reset_backoff_on_progress: bool false 获得新的明确 RTT 样本后,将已有重试计数限制到最多1并重新计算期限 可缩短过长退避,但可能增加重传压力;重传包 ACK 不触发调整

默认三个选项全关。只评估期限调度可使用:

socket.set_recovery_options(RecoveryOptions {
    deadline_driven: true,
    ..RecoveryOptions::default()
}).await?;

独立评估退避调整时,只设置 reset_backoff_on_progress: true。修改单个字段而保留其他设置时,先读取 recovery_options(),修改后再调用 setter。尽量在业务发送前配置;重新设置会重置探测进展起点,但保留已发探测的普通 RTO 回退期限。

探测条件与时间

必须在启用后获得有效 RTT 反馈、待发送队列为空,且仅有一个从未重传的数据报在途。合包最多8帧,所有成员都必须仍未确认,并作为同一个新数据报序号完整重放。使用发送策略时,待发送不可靠消息会阻止探测,整组还必须容纳于单次发送预算;不会提前重传整个在途窗口。

等待至少为 max(1 ms, 设置下限, ceil(1.5 × 平滑 RTT)),起点是确认进展或新一轮在途发送。零值和不足1 ms的设置按1 ms处理,时间精度为毫秒。没有新进展时只探测一次,重传历史也会阻止再次探测同一数据报。10 ms是下限,不是交付期限;慢链路可能等待更久。

探测保留原始绝对 RTO 期限。原包与探测都丢失时,普通超时仍在原期限触发。探测不增加正常超时退避次数,探测/重传的 ACK 不进入 RTT 采样(Karn 规则)。已到期普通重传优先;真实 NACK/超时仍按原规则关闭后续小包合并。

时间戳修正与不变的估算公式

编译恢复功能后,在获得发送队列锁并处理反馈后刷新后续发包时间,避免锁等待使新消息期限回溯。即使三个选项全关也包含该修正;ACK RTT样本仍使用收到反馈时的时间。

基础公式不变:SRTT = (4 × 旧SRTT + 样本) / 5,整数毫秒;RTO = clamp(1.5 × SRTT, 50 ms, 12,000 ms)。普通退避仍按1.5倍递增,最高12,000 ms。进展退避只在显式启用时调整已有重试级别。没有新增自适应拥塞窗口、带宽估计或发送速率控制。

关闭

socket.set_recovery_options(RecoveryOptions::default()).await?;

关闭后不再发新探测、不再使用期限维护或进展退避;已发探测仍保留普通回退直到结束。编译时的时间戳修正仍在,去掉 recovery-policy 才恢复原反馈/计时路径。恢复策略可以重置为默认关闭,发送策略则没有恢复“未配置”状态的接口。

实测收益和代价

2026年10月4日,受控链路三轮中位数。以下是历史恢复实验,独立于 10 月 12 日未启用 recovery-policy 的横向 benchmark。

场景 1.1.0 仅期限唤醒 10 ms最小探测
单次尾包丢失 81.91 ms 55.86 ms 14.94 ms
单次ACK丢失 83.00 ms 55.86 ms 14.54 ms
连续丢失两次目标发送 168.72 ms 132.15 ms 55.06 ms
带宽/RTT/队列骤变 4,819.20 ms 5,095.62 ms 5,097.49 ms

尾包/ACK使用100 Mbps、2 ms RTT,完成时间含可靠确认;骤变从100 Mbps、30 ms RTT切换为2 Mbps、800 ms RTT,每方向32 KiB队列,校验192条有序800 B回显,以最后一条回显计算完成时间。两类负载不同,约15 ms不能推广到800 ms RTT路径。

持续吞吐可能下降:1024连接、64 B、无注入丢包的批量接口,本轮默认构建140.68 MiB/s,开启探测118.74 MiB/s;800 B对应466.86和393.23 MiB/s。持续负载延迟也有升有降。这是三轮中位数,不表示统计显著性或普遍收益。吞吐优先时保留默认构建;短请求、稀疏消息和尾包敏感连接再分别评估。

全部配置参数 · 发送策略 · 性能评估方法

Clone this wiki locally