EasyTier 组网带宽限制与连接稳定性优化实践

问题背景

在 EasyTier 组网场景中,当某个节点占用高带宽时,会导致子网内其他节点与该节点的连接出现阻塞甚至断连的问题。这是一个典型的 bufferbloat 和队列管理问题。

问题现象

  • 高带宽占用节点(如进行大文件传输、视频流等)会影响同一子网内其他节点的连接稳定性

  • 其他节点与该高带宽节点之间的连接会出现延迟增加、丢包、甚至断连

  • 网络吞吐量受影响,整体用户体验下降

解决方案验证

通过 iperf3 进行带宽测试验证:

# 不限制带宽时:连接阻塞、断连问题复现
iperf3 -c <target> -t 60

# 限制带宽后:问题解决,连接稳定
tc qdisc add dev tun0 root cake bandwidth 40mbit
iperf3 -c <target> -t 60

验证结论: 使用 tc qdisc cake 进行带宽限制是有效的解决手段。

本文档记录如何在系统启动时自动执行流量控制命令:

/usr/sbin/tc qdisc add dev tun0 root cake bandwidth 40mbit

并在服务停止时自动清除:

/usr/sbin/tc qdisc del dev tun0 root

这个配置在 EasyTier 组网场景下经过验证,能有效解决高带宽占用导致的连接阻塞问题。

核心概念

tc(Traffic Control)

tc 是 Linux 提供的用户空间命令行工具,用于配置内核网络协议栈的流量控制机制。它能对网络接口的出口流量进行整形、调度、优先级分类、过滤、丢弃等操作。

主要用途:

  • 限速(设置最大带宽)

  • 公平队列,防止单个连接霸占全部带宽

  • 差分服务(对不同业务流提供不同优先级)

  • 模拟延迟、丢包(测试用途)

qdisc(Queuing Discipline)

qdisc 是 traffic control 的基本构件,可以理解成"数据包在发送之前所经历的排队策略"。每个网络接口都有至少一个 qdisc,负责管理出口数据包:何时发送、按什么顺序发送、何时丢弃。

重要概念:

  • root qdisc:每个接口只能有一个根 qdisc,通过 tc qdisc add dev tun0 root 附加

  • 无类 qdisc(classless):只对数据包整体起作用,如 pfifo_fast、fq_codel、cake

  • 有类 qdisc(classful):内部可以包含多个子类,如 HTB、PRIO

CAKE(Common Applications Kept Enhanced)

CAKE 是一个现代、智能、高度集成的排队规则,由 OpenWrt 社区和 Bufferbloat 项目主导开发,旨在解决家庭/边缘网络中的 bufferbloat(缓冲区膨胀)问题。

核心能力:

  1. 集成整形与调度:直接配置带宽限制(bandwidth 参数),无需额外的整形器

  2. 主动队列管理(AQM):使用改进版 Codel 算法,在队列堆积前主动丢包/标记,大幅降低延迟

  3. 公平队列:在主机之间、流之间进行公平调度,防止单一下载占满带宽

  4. 差分服务(DiffServ)处理:自动识别 DSCP 标记,优先发送高优先级流量

常用参数:

  • bandwidth:设置带宽限制

  • nat:自动处理 NAT 场景下的公平性

  • wash:清除 DSCP 标记,避免干扰

  • diffserv3/diffserv4:选择差分服务模式

  • ack-filter:优化 TCP ACK 处理

典型用法:

tc qdisc add dev eth0 root cake bandwidth 100mbit
tc qdisc add dev tun0 root cake bandwidth 40mbit nat

一、systemd Linux 平台解决方案

1. 创建 systemd 服务文件

创建 /etc/systemd/system/tc-cake-tun0.service

[Unit]
Description=CAKE qdisc on tun0 (40mbit)
After=network-online.target docker.service sys-subsystem-net-devices-tun0.device
Wants=network-online.target docker.service
Requires=sys-subsystem-net-devices-tun0.device

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/tc qdisc add dev tun0 root cake bandwidth 40mbit
ExecStop=/usr/sbin/tc qdisc del dev tun0 root
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

关键配置说明:

  • Type=oneshot:适用于执行一次性命令就退出的服务

  • RemainAfterExit=yes:让 systemd 认为服务在命令退出后仍然"活动",停止时才会执行 ExecStop

  • After=docker.service:确保 Docker 引擎启动完成

  • Requires=sys-subsystem-net-devices-tun0.device:等待 tun0 设备出现后再启动

2. 启用和启动服务

sudo systemctl daemon-reload
sudo systemctl enable tc-cake-tun0.service
sudo systemctl start tc-cake-tun0.service

3. 验证和测试

# 查看 qdisc 是否存在
tc qdisc show dev tun0

# 查看服务状态
systemctl status tc-cake-tun0.service

# 测试停止与清除
sudo systemctl stop tc-cake-tun0.service
tc qdisc show dev tun0

# 重新启动
sudo systemctl start tc-cake-tun0.service

二、iStoreOS(OpenWrt)平台解决方案

iStoreOS 基于 OpenWrt,没有 systemd,使用 procd 作为服务管理器,配置方式完全不同。

使用 SQM QoS 图形界面(推荐)

这是最简单、最稳定的方式:

  1. 登录 LuCI → 网络 → SQM QoS

  2. 选择接口 tun0

  3. 选择队列规则 cakepiece_of_cake.qos

  4. 填写带宽 40000 kbit/s

  5. 可选:开启 nat、wash 等选项

SQM 队列脚本说明:

脚本名称

说明

piece_of_cake.qos

最简单配置:直接使用 cake 替代 HTB 和 fq_codel

layer_cake.qos

使用 cake 的 diffserv profile 实现分层优先级

simplest.qos

HTB 限速 + cake 队列

simple.qos

三层优先级方案(默认)

simplest_tbf.qos

TBF 限速 + cake 队列

最佳实践: 相比用tc的方案,在 iStoreOS 上优先使用 LuCI 的 SQM QoS 界面,完全不需要接触命令行。

三、Windows 平台解决方案

Windows 没有原生内置类似 Linux tc 的接口级流量整形工具,需要根据场景选择替代方案。

注:暂时还没有测试

第三方网络限速工具

使用 NetLimiter、cFosSpeed 等工具。

以 NetLimiter 为例:

创建开机启动脚本 start-limit.bat

"C:\Program Files\NetLimiter 4\nlclientapp.exe" /limit "Ethernet 3" out 40 mbit

创建停止脚本 stop-limit.bat

"C:\Program Files\NetLimiter 4\nlclientapp.exe" /dellimit "Ethernet 3" out

将快捷方式放入启动文件夹(shell:startup)或通过任务计划程序设置自动运行。

PowerShell QoS 策略(功能有限)

# 添加 QoS 策略
New-NetQosPolicy -Name "LimitVPNOut" -ThrottleRateActionBitsPerSecond 40MB `
                 -IPProtocol Any -PolicyStore ActiveStore

# 删除策略
Remove-NetQosPolicy -Name "LimitVPNOut"

严重限制:

  • 影响所有出站流量,不区分接口

  • 需要手动启停

  • 无法自动跟随接口状态

不推荐使用,除非是临时测试环境。

EasyTier 组网最佳实践

1. 带宽设置建议

基于 iperf3 测试验证,推荐的带宽限制配置:

# 对于 40Mbps 物理链路,建议限制为 30-35Mbps
tc qdisc add dev tun0 root cake bandwidth 30mbit

# 对于 100Mbps 物理链路,建议限制为 80-90Mbps
tc qdisc add dev tun0 root cake bandwidth 80mbit

# 启用 NAT 优化(如果节点在 NAT 后面)
tc qdisc add dev tun0 root cake bandwidth 40mbit nat

设置原则:

  • 留出 10-20% 的安全余量,避免队列拥塞

  • 考虑物理链路的实际可用带宽(扣除其他流量)

  • 在对称链路上可以双向限制,非对称链路需分别设置

2. 监控和验证

定期测试连接稳定性:

# 持续监控连接状态
watch -n 1 'tc qdisc show dev tun0'

# 测试带宽和延迟
iperf3 -c <target_node> -t 30

# 测试连接稳定性(长时间)
iperf3 -c <target_node> -t 300

3. 故障排查

如果出现连接问题,按以下步骤排查:

  1. 检查 qdisc 是否生效

    tc qdisc show dev tun0
    
  2. 检查服务状态

    systemctl status tc-cake-tun0.service
    journalctl -u tc-cake-tun0.service -n 50
    
  3. 检查带宽设置是否合理

    • 调整 bandwidth 参数,避免过度限制或限制不足

    • 使用 iperf3 测试不同带宽设置下的表现

  4. 检查 EasyTier 节点状态

    • 确认节点是否正常连接

    • 查看节点日志,排查其他可能的问题

4. 部署建议

生产环境部署:

  • 先在测试环境验证配置效果

  • 使用 systemd service 或 hotplug 确保配置持久化

  • 设置监控告警,及时发现配置失效

  • 定期备份配置文件

多节点部署:

  • 在所有高带宽节点上应用相同策略

  • 在中心节点或网关节点统一管理流量控制

  • 考虑使用配置管理工具(如 Ansible)批量部署

通用最佳实践建议

  1. 优先使用平台原生方案

    • Linux: systemd service

    • OpenWrt/iStoreOS: SQM QoS

    • OpenVPN: 内置 shaper

  2. 在网关侧统一管理:EasyTier 组网中,建议在中心节点或高带宽节点上进行流量整形,而不是在每个客户端单独配置。

  3. 关注设备可用性:确保服务启动时目标网络接口(tun0)已存在,使用 .device 单元或 hotplug 事件机制。

  4. 错误处理:配置失败不应阻塞系统启动,但要保留日志便于排查问题。

  5. 测试验证:使用 iperf3 验证配置效果,确保高带宽场景下连接稳定性。

技术背景:为什么 CAKE 能解决问题

EasyTier 组网中的连接阻塞问题本质上是一个 bufferbloat 问题:

问题根源

  • 当某个节点占用高带宽时,网络接口的发送队列会迅速堆积

  • 大量数据包在队列中等待,导致延迟急剧增加

  • TCP 连接的超时重传机制触发,导致连接断连

  • 其他节点的数据包在队列中排不上队,被"饿死"

CAKE 的解决机制

  1. 主动队列管理(AQM):在队列堆积前主动丢包/标记,向发送方发出拥塞信号

  2. 公平队列:确保不同连接/流之间公平分享带宽,防止单个连接占满全部带宽

  3. 带宽整形:严格控制发送速率不超过设定值,从源头避免队列堆积

  4. 低延迟优化:即使在高负载情况下,也能保持较低的延迟

这就是为什么通过 iperf3 验证,使用 CAKE 限制带宽后,EasyTier 连接稳定性得到显著改善的原因。