Sunshine 串流出现 Buffer overrun 丢包时如何用 tc 为 Sunshine 流量做限速整形?
【免费下载链接】SunshineSelf-hosted game stream host for Moonlight.项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine
当 Sunshine 主机(宿主机)到 Moonlight 客户端的网络路径上,宿主机一侧的链路速度明显快于最慢的那一段时,串流过程中可能出现大量丢包,即docs/troubleshooting.md中描述的 “Packet loss (Buffer overrun)” 现象。Sunshine 以 60 fps 计算每 16 ms 突发发送一次流数据,这些突发无法被慢速链路及时转发,只能缓存在路径中间的设备里;码率足够高时缓冲区就会溢出、数据被丢弃。文档给出的典型场景是:宿主机为 2.5 Gbit/s 链路而客户端只有 1 Gbit/s 或 Wi-Fi,或者 1 Gbps 的宿主机对端只有 100 Mbps 网卡。
解决思路是把宿主机网卡(NIC)上 Sunshine 流量的发送速率压到与慢速段匹配的水平。文档提供了两条路径:直接降低 NIC 整体发送速率(简单粗暴的 workaround),或者用 Linux 内核的流量整形(traffic shaping)规则只对 Sunshine 的串流流量限速,其他流量不受影响。本文介绍后者的具体操作步骤。
适用前提与两条解决路径
- 该方法只适用于Linux 主机,命令需要
sudo权限执行。 - 执行后会对
<NIC>指定的网卡修改 qdisc(排队规则),只影响该网卡的发送整形;重启后规则不会保留(文档明确说明 “This is not persistent on reboots”)。 - 如果你使用的是 Sunshine> 0.23.1,文档指出其改进了网络代码,可能已经缓解甚至彻底解决该问题(无需降低 NIC 速度),可以优先升级验证。
- 更简单的替代方案:直接降低主机 NIC 的发送速率,例如 2.5 Gbps 降到 1 Gbps、1 Gbps 降到 100 Mbps,使其与最慢网络段一致。文档将其描述为 workaround;tc 方案则是“技术上更进阶”的做法,因为只有 Sunshine 流量被限速。
用 tc 为 Sunshine 流量配置 HTB 整形
以下命令来自docs/troubleshooting.md。执行前请替换:
<NIC>:替换为宿主机上承担串流发送的网卡接口名(这是文档命令中唯一的占位符);- 第 4 步的
rate 1000mbit ceil 1000mbit:文档示例按 1 Gbit/s 配置,对应“宿主机比客户端快”的场景,请按你网络路径上的实际瓶颈段调整该限速值; - 第 3 步的
rate 10000mbit是文档示例中其他流量的默认类速率,按你的网卡能力对照调整。
# 1) Remove existing qdisc (pfifo_fast) sudo tc qdisc del dev <NIC> root # 2) Add HTB root qdisc with default class 1:1 sudo tc qdisc add dev <NIC> root handle 1: htb default 1 # 3) Create class 1:1 for full 10 Gbit/s (all other traffic) sudo tc class add dev <NIC> parent 1: classid 1:1 htb \ rate 10000mbit ceil 10000mbit burst 32k # 4) Create class 1:10 for Sunshine game stream at 1 Gbit/s sudo tc class add dev <NIC> parent 1: classid 1:10 htb \ rate 1000mbit ceil 1000mbit burst 32k # 5) Filter UDP source port 47998 into class 1:10 sudo tc filter add dev <NIC> protocol ip parent 1: prio 1 \ u32 match ip protocol 17 0xff \ match ip sport 47998 0xffff flowid 1:10各步骤的作用(按文档注释):
- 删除网卡上已有的 qdisc(例如
pfifo_fast),为挂接新规则做准备; - 添加 HTB 根 qdisc,默认类为
1:1,未命中过滤器的流量都走这个类; - 创建类
1:1承载全部其他流量(文档示例速率 10 Gbit/s); - 创建类
1:10承载 Sunshine 串流,文档示例限速 1 Gbit/s; - 添加过滤器:匹配UDP 源端口 47998的报文进入类
1:10,47998 是 Sunshine 游戏串流的端口。
完成以上配置后,文档描述的预期结果是:只有 Sunshine 的流量被限制在设定的 1 Gbit,网卡上的其他流量不受影响。文档没有给出tc命令执行后的固定输出样例,判断依据就是串流不再出现缓冲区溢出式的大面积丢包。
两点需要注意:
- 如果你为游戏串流使用了不同的端口,需要调整最后一条命令(过滤器)中的
sport 47998; - 规则不随重启保留,每次重启后需要重新执行。若不想再限速,执行第 1 步的
sudo tc qdisc del dev <NIC> root即可移除现有 qdisc(移除后接口恢复默认队列行为)。
用 iPerf3 验证网络路径是否满足串流要求
docs/troubleshooting.md给出的“Network performance test”方法可用于判断路径质量,帮助确认限速值是否设得合理:对实时游戏串流而言,网络路径最重要的不是纯带宽,而是稳定性与一致性——低延迟、低抖动、尽量无丢包。
在 Sunshine 主机上以服务器模式启动iperf3:
iperf3 -s在客户端设备上执行 60 秒的反向(server → client)UDP 测试,{HostIpAddress}替换为主机 IP,示例码率 50 Mbps:
iperf3 -c {HostIpAddress} -t 60 -u -R -b 50M观察客户端输出中的丢包率(packet loss)和抖动(jitter):文档给出的参考是丢包率保持在 5% 以下、抖动低于 1 ms 为理想状态。测试远程(互联网)连接时需要从宿主机转发 5201 端口(TCP 和 UDP)。
限制与相关分支
- 规则重启后失效,需要重新配置;文档未提供将其持久化的方法。
- 如果丢包与码率/链路速度差无关,文档还提到一个独立问题:“Packet loss (MTU)”——个别客户端(文档举例为某 LG TV)在主机 MTU 为 1500/1472 时丢包 30–60%,把承载串流的网卡 MTU 设为 1428 后丢包降为 0。文档明确说这是最后手段(last resort),原因尚不明确,与本文的 tc 整形是两条独立的排查方向。
- Sunshine > 0.23.1 的网络改进可能使上述限速不再必要;升级后若问题消失,可移除 tc 规则恢复 NIC 全速。
【免费下载链接】SunshineSelf-hosted game stream host for Moonlight.项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考