Linux流控队列深度对比:fq、fq_codel与CAKE源码机理与选型
测试环境:本文实测数据来自 DMIT 的 VPS。
很多朋友给 VPS 开启 BBR 甚至 BBRplus 之后,会发现一个普遍现象:测速跑单线程带宽似乎上去了,但实际看 4K 视频、打游戏或者开网页时依然有明显的卡顿感,尤其是晚高峰丢包率上升时更为严重。
这背后的根本原因在于:你只调整了“拥塞控制算法(Congestion Control)”,却没有配置好底层的“排队规则(qdisc / Queueing Discipline)”。
在我们的横评指南 《Linux拥塞控制与内核源码级横评:BBR、BBRplus与第三方内核》 中曾提到,拥塞控制决定的是“什么时候发、发多快”,而排队规则(fq / fq_codel / CAKE)决定的是“当数据堆积在网卡缓冲区时,先丢谁的包、按什么顺序发包”。本文从 Linux 内核源码实现剖析三大主流队列规则,并提供选型参考。
快速选型速查表
在深入源码之前,先看三者的横向对比结论:
| 队列规则 (qdisc) | 核心算法与机制 | 资源消耗 | 抗 Bufferbloat(缓冲区膨胀)能力 | 最佳应用场景 |
|---|---|---|---|---|
| fq (Fair Queue) | 基于 Socket 的公平队列 + 精确 Pacing 时钟整形 | 极低 (单核首选) | 中等(依赖拥塞算法主动限速) | 纯拉大文件下载、单核 512M 小鸡、原生 BBR 标配 |
| fq_codel | CoDel 主动队列管理 (AQM) + 1024 桶流隔离 | 中等 | 优秀(排队延迟超过阈值主动丢包) | Debian/Ubuntu 通用服务器默认、常规建站 |
| CAKE | 8-way 组合哈希 + DiffServ 优先级队列 + ACK 压缩反压 | 稍高(CPU 开销略高于 fq_codel) | 顶级 (满载延迟基本不抖动) | XanMod 内核用户、多核 VPS、晚高峰跨国弱网、兼顾游戏与测速 |
一、 源码级原理解析:三大队列是怎么工作的?
1. fq (net/sched/sch_fq.c):为 Pacing 而生
在 Linux 内核源码树中,sch_fq.c 的核心结构极其简洁。它本质上不是为了复杂调度而设计的,而是 Google 为了配合 BBR 的节奏发包(Pacing)而专门定制的。
1 | /* net/sched/sch_fq.c 源码核心结构片段 */ |
工作机理:
- Pacing 时钟约束:当 BBR 算法计算出当前的瓶颈带宽后,会给每个
sk_buff打上时间戳。fq并不直接一股脑把包推给网卡驱动,而是将其放入红黑树中,只有当当前系统时间>= time_next_packet时才允许出队。 - 优点:彻底消除了突发大流量(Burst)将交换机和中间路由器缓存瞬间打爆的情况。
- 缺点:它只管节奏,对“突发排队”没有主动防御机制。如果你遇到了开启调优后依然测速异常的情况,建议对照 《BBR 开启后没有速度提升?排查这 5 个关键原因》 逐步排查 NAT 或硬件队列配置。
2. fq_codel (net/sched/sch_fq_codel.c):智能丢包与小包插队
fq_codel 是当代 Linux 系统的通用标准。它将 Fair Queueing(公平队列)与 CoDel(Controlled Delay,受控延迟)结合在一起。
核心源码逻辑:
- 区分肥流与瘦流(Fat vs Sparse Flows):
- 像视频流、大文件下载这种持续占满带宽的叫做“肥流”;
- 像 SSH 击键、DNS 查询、TCP 握手包这种偶尔发一个包的叫做“瘦流”。
fq_codel会无条件优先清空“瘦流”队列,这也是为什么开启 fq_codel 时,后台满速下载你敲 SSH 也不会感觉卡顿的原因。
- CoDel 驻留时间检测:
- 源码跟踪每个数据包在队列里的排队时间。如果排队持续时间超过
target(默认 5ms),CoDel 会判定主机遭遇了 Bufferbloat,立即开始按丢包状态机进行主动丢弃(Drop),强迫客户端 TCP 降速。
- 源码跟踪每个数据包在队列里的排队时间。如果排队持续时间超过
3. CAKE (net/sched/sch_cake.c):流控终极解决方案
CAKE(Common Applications Kept Enhanced)由网络专家开发并合并入 Linux 主线内核,是当前抗弱网抖动最强力的利器。
相比 fq_codel 的三大源码级升级:
- 8-way Set Associative Hash(8路组相联哈希):
- 普通 fq_codel 遇到大量并发连接时,不同连接可能由于哈希冲突被分到同一个桶里;CAKE 借鉴了 CPU 缓存算法,通过 8 路组合哈希将冲突概率降低了数个数量级。
- DiffServ 自动分级调度(Tin 架构):
- 源码内置了 3 级(Bulk 批量、Best Effort 普通、Voice/Interactive 实时语音交互)优先级“锡罐(Tins)”。低延迟数据包自动插队,且各级之间按权重平滑分配,绝不饿死低优先级流量。如果希望用上 CAKE,可以参考 《一键更换为 XanMod 内核实战》 部署新版内核,再手动设置
net.core.default_qdisc=cake开启(XanMod 默认拥塞算法是 BBRv3,队列规则需手动指定)。
- 源码内置了 3 级(Bulk 批量、Best Effort 普通、Voice/Interactive 实时语音交互)优先级“锡罐(Tins)”。低延迟数据包自动插队,且各级之间按权重平滑分配,绝不饿死低优先级流量。如果希望用上 CAKE,可以参考 《一键更换为 XanMod 内核实战》 部署新版内核,再手动设置
- ACK 过滤(ACK Filtering):
- 在高并发上传时,大量冗余的反向 ACK 包会抢占上行带宽;CAKE 会在队列中自动合并丢弃旧的累积 ACK,释放珍贵的上行信道。
二、 场景选型指南
场景 1:512MB / 1GB 单核低配 VPS
- 推荐组合:
fq+BBR - 理由:CAKE 在极高带宽突发时会占用更多的软中断(SoftIRQ)开销。单核低配小鸡建议保持最精简的
fq,不给 CPU 增加计算负担。
场景 2:跨国晚高峰代理、中转落地机、多核 VPS
- 推荐组合:
CAKE+BBR - 理由:晚高峰公网丢包率明显上升时,单纯靠重传会造成雪崩式队列阻塞。CAKE 能够精准保住握手包与关键信令包,平滑弱网延迟。若需定位跨国骨干网在哪个跳数发生了严重拥塞,可直接通过 《NextTrace教程:开源可视化路由追踪》 实时追踪路径质量。
三、 实操:如何在 VPS 上切换并验证?
步骤 1:检查当前生效的队列与拥塞控制
1 | # 查看当前网络接口生效的队列规则 |
步骤 2:切换为 CAKE + BBR
在 Debian 11+ / Ubuntu 20.04+ 或安装了定制内核的系统上,直接写入 sysctl 配置:
1 | sudo tee /etc/sysctl.d/99-network-qdisc.conf << 'EOF' |
如果在调优和管理多服务 VPS 期间遇到了端口枯竭、进程假死等深层异常,可以随时查阅我们的 《Linux网络与VPS日常运维故障全景排查手册》 快速定位问题。