WWDC Quick Look 💓 By SwiftGGTeam
Reduce network delays with L4S

Reduce network delays with L4S

观看原视频

Highlight

iOS 17 和 macOS Sonoma 内置了 L4S(Low Latency, Low Loss, Scalable throughput)支持:使用 URLSession 或 Network framework 的 HTTP/3 和 QUIC 流量自动获得队列管理优化,在拥挤网络中将延迟降低 50%、丢包率从 40% 压到接近零,无需改动一行代码。


核心内容

你在咖啡馆打视频电话,旁边有人下载 50GB 的游戏。你的画面开始卡顿,声音断断续续。问题出在网络瓶颈处的队列——它失控了。

当一个网络被多个设备同时使用时,瓶颈节点(通常是 ISP 的路由器)处的数据包会不断堆积。传统做法是:让队列一直增长,直到缓冲区满了再丢包。发送方看到丢包后才意识到拥塞,开始降速。这个过程有两个问题:一是排队本身就带来了延迟,二是丢包意味着数据需要重传,进一步恶化延迟。

L4S 改变了这个机制。它让发送方在队列开始形成时就感知到拥塞——在丢包发生之前。

实现方式是三步协作。第一步,发送方在 IP 包头使用 ECN(显式拥塞通知)标记,声明自己愿意配合拥塞控制。第二步,网络瓶颈设备检测到队列开始增长时,在通过的数据包上打上不同的 ECN 标签,表示”前方有拥塞”,然后继续转发而不是丢弃。第三步,接收方统计这些被标记的数据包数量,通过协议反馈给发送方。发送方据此微调发送速率,在队列变得过大之前就放慢速度。

这个闭环让数据包几乎不会被丢弃,队列长度始终很短,延迟保持在接近物理下限的水平。

Apple 的实测数据显示:在一个最小 RTT 为 20ms 的测试网络中,没有 L4S 时数据包最差延迟达到 45ms,开启 L4S 后降到了 25ms 以下——减少了超过 50%。丢包率从 40% 以上降至接近零。视频通话的卡顿几乎完全消失,接收帧率大部分时间维持在 25fps 以上,而没有 L4S 时帧率有时会直接掉到 0。


详细内容

自动获得 L4S:URLSession 和 Network framework

如果你的 app 使用 URLSession 或 Network framework,并且传输协议是 HTTP/3 或 QUIC,L4S 已经内置了。不需要写任何代码。

如果你用的是 HTTP/2 或 TCP,iOS 17 和 macOS Sonoma 也为下载方向的流量内置了 L4S 支持。

这意味着绝大多数 app 自动受益。你只需要确保 app 使用了这些高层 API 和现代协议。

自定义协议:需要手动实现

如果你的 app 使用自定义传输协议(如自建的 UDP 协议或 WebRTC),需要自己实现三个行为来支持 L4S(09:01):

  1. 可扩展的拥塞控制算法 — 发送方需要能根据网络中的 ECN 拥塞反馈调整发送速率
  2. ECN 验证机制 — 检查网络是否对 ECN 标记做了干扰(如”漂白”ECN 位),确保仅在 ECN 通路正常时发送 L4S 流量
  3. ECN 反馈中继 — 作为接收方时,将收到的 ECN 拥塞标记回传给发送方

RFC 9330 是 L4S 的标准文档,可作为实现参考。

如果你的自定义协议基于 Network framework,可以使用数据包元数据(packet metadata)上的 ECN 属性来发送和接收 ECN 标记。如果使用 BSD socket,可以用 setsockoptsendmsg/recvmsg 系统调用来处理 ECN 标记。

服务端配置

L4S 需要服务端配合。如果你的 app 使用 QUIC,服务端的 QUIC 实现也需要支持 L4S 和 ECN 标记(11:19)。市面上的 QUIC 服务端实现很多,可以询问你的服务端或 CDN 提供商如何开启 ECN 和 L4S。即使他们还不支持发送 L4S 流量,至少可以开启 ECN 来接收 L4S 流量。

如果你的 app 使用 TCP,需要在服务端的 TCP 实现中添加 L4S 支持。Linux 服务器可以参考 GitHub 上的 L4S 项目页面。

搭建测试网络

要测试 L4S 效果,需要让网络满足两个条件(12:31):

  1. 网络必须允许 ECN 标记通过,不能干扰或清除这些标记
  2. 瓶颈节点必须支持 L4S 队列管理

macOS Sonoma 的”互联网共享”(Internet Sharing)功能内置了 L4S 队列管理,可以作为测试瓶颈节点。在系统设置中开启互联网共享后,Mac 本身就是网络上的一个额外跳点。用下面的命令限制共享接口的带宽,Mac 就成了网络瓶颈:

sudo ifconfig en1 tbr 10Mbps

关键点:

  • ifconfig en1 — 指定互联网共享使用的网络接口(需替换为实际接口名,如 en1
  • tbr 10Mbps — 设置令牌桶速率(token bucket rate),将带宽限制为 10Mbps,让 Mac 成为瓶颈节点
  • 要恢复带宽限制,把 10Mbps 改成 0 再运行一次,或重启 Mac

测试设备连接这个 Mac 共享的网络后,所有经过的流量都会经过 L4S 队列管理。

在设备上开启 L4S

iOS 17 和 macOS Sonoma 中,L4S 会逐步推送给随机用户。为了确保测试设备开启了 L4S,有两种方式:

macOS — 终端命令(15:36):

sudo defaults write -g network_enable_l4s -bool true

iOS — 开发者设置:

在”设置”的开发者选项中,找到并开启 L4S 开关。

关键点:

  • defaults write -g-g 是全局域(global domain),让设置对所有应用生效
  • network_enable_l4s — 控制 L4S 是否启用的全局键
  • -bool true — 显式开启 L4S;设为 false 即可关闭
  • 如果你的网络或服务端不支持 L4S,TCP 和 QUIC 会自动回退到传统模式,不会影响连接

核心启发

1. 在视频通话 app 中监控 L4S 效果

做什么:在现有视频通话 app 中添加网络诊断面板,对比 L4S 开启和关闭时的 RTT 分布和丢包率。

为什么值得做:L4S 最直接影响的就是实时通信 app。一个可视化面板可以让开发者和用户直观看到 L4S 带来的改善,也方便向服务端团队证明开启 L4S 的价值。

怎么开始:使用 Network framework 的 NWConnection 监控连接状态,收集 RTT 样本。在 iOS 17+ 的设备上,通过 defaults 命令切换 L4S 开关,对比两组数据。

2. 用 Internet Sharing 做网络质量测试工具

做什么:写一个命令行工具,自动配置 Mac 互联网共享作为 L4S 测试瓶颈,然后跑一组网络测试,生成 L4S 开关对比报告。

为什么值得做:手动配置 ifconfig tbr 和切换 L4S 很繁琐。一个自动化脚本可以让任何人在自己的 Mac 上快速搭建 L4S 测试环境,用于验证 app、网络设备或服务端的 L4S 兼容性。

怎么开始:用 ProcessNSTask 执行 ifconfigdefaults 命令,调用 URLSession 跑一组请求,收集 URLSessionTaskMetrics 中的 transactionMetrics,对比延迟和丢包数据。

3. 给自定义 UDP 协议加上 L4S 支持

做什么:为一个基于 UDP 的自定义传输协议实现 RFC 9330 兼容的 L4S 拥塞控制。

为什么值得做:很多游戏和实时应用使用自定义 UDP 协议,这些 app 从 L4S 获益最大,但也需要手动实现支持。这是一个理解现代拥塞控制的好机会。

怎么开始:从 Network framework 的 NWConnection 开始,在发送数据包时设置 metadata.ecn 属性。阅读 RFC 9330 了解 ECN 反馈循环的实现细节。实现一个简单的基于 ECN 标记的速率调整算法。

4. 为 CI 流水线添加 L4S 兼容性检查

做什么:在 app 的 CI 测试中加入 L4S 兼容性测试——确保在 L4S 开启和关闭的网络上 app 都能正常工作。

为什么值得做:Apple 会逐步向用户推送 L4S。如果你的 app 或其依赖的第三方库对 ECN 标记有异常行为,可能在 L4S 网络上出现连接问题。在 CI 中提前测试可以避免用户遇到这些问题。

怎么开始:在 CI Mac 上配置 Internet Sharing 并限制带宽,分别在 L4S 开启和关闭的情况下跑 app 的网络测试用例。使用 Feedback Assistant 报告任何异常。


关联 Session

评论

GitHub Issues · utterances