前阵子有个做运维的朋友找我吐槽,说公司明明拉了千兆专线,但一到下午全员视频会议,画面照样糊成马赛克,语音断断续续。他们查了半天,核心交换机出口带宽占用才 60%。这种“链路没堵死但也卡”的现象,我见过太多次了。问题不在带宽总量,而在网络对流量一视同仁——关键业务和下载任务挤在同一个队列里,谁都没被优先照顾。QoS(Quality of Service,服务质量)要解决的,正是这种“同一根管道里有人急有人不急,真遇到瓶颈大家全卡”的困境。
这篇文章把 QoS 基本原理完整拆一遍,围绕“为什么加了带宽还是卡”“QoS 到底能改哪几件事”“部署时最容易踩哪些坑”三条线展开。准备上手网络优化的工程师、刚接触 QoS 的运维同学,看完可以拿这套思路直接分析自己的组网场景。
1. QoS 要解决的首要问题:资源不够的时候怎么办
先明确一个概念:QoS 不增加总带宽,它做的是资源分配。网络设备转发报文依赖三种资源——链路带宽、交换接口的内存队列(Buffer)、CPU 处理能力。这些资源在任何时刻都是有限的,当业务流量之和超过资源上限,必然有一部分报文要等待、丢弃或延迟处理。传统网络协议栈默认对所有报文一视同仁,谁先到谁先走,谁也不比谁特殊。这种模式叫“尽力而为”(Best Effort)。
1.1 尽力而为模式的尴尬
尽力而为不是设计缺陷,它保证了网络简单、健壮、成本低。但它的缺点在业务多样化之后暴露得很彻底:一条链路上同时跑着语音、视频会议、数据库同步、软件升级下载时,所有报文混在同一个队列里按到达顺序发送。下载任务通常是长连接、大流量、对时延不敏感;语音和视频则相反,报文小、实时性强、对时延极敏感。一旦链路出现瞬时拥塞,下载报文填满队列,语音报文排在后面,通话就出现卡顿。
更麻烦的是,尽力而为模式拥塞时多用“尾丢弃”(Tail Drop)——队列满了,新来的报文直接丢。TCP 对丢包很敏感,一旦丢包就触发超时重传和拥塞窗口减半,导致链路利用率周期性跌到很低;而 UDP 承载的语音、视频流量根本不感知拥塞,该丢还是丢。于是出现一个反直觉的结果:带宽明明有富余,关键业务照样卡。
1.2 QoS 的三个核心动作
既然资源有限,QoS 的思路就是做取舍。它由三个核心动作组成:
- 分类识别:确认“这个报文是谁”,属于哪类业务,该享受什么待遇。
- 区分处理:在转发、排队、丢弃等环节对不同类别的报文给予不同待遇,比如优先发送、预留带宽、降低丢包概率。
- 资源控制:对某些不重要的流量做限速、整形,防止它们抢占关键业务的资源。
打个比方:一条双向两车道的公路,混行状态下救护车和私家车堵在一起。QoS 就是先识别出哪些是救护车(分类),在路口给它单独放行(调度),同时对长期占用道路的货车限制通行时段(限速)。公路的总宽度没法变,但关键车辆的通行体验可以大幅改善。
理解了这一点,再看后面所有机制都会很顺:一切都是为了在拥塞时把资源让给“该让的流量”。
2. 衡量服务质量的四个硬指标:带宽、时延、抖动、丢包
要量化“服务质量”,得有评价维度。QoS 讨论中绕不开的四个指标是带宽(Bandwidth)、时延(Latency)、抖动(Jitter)和丢包(Packet Loss)。很多人以为带宽够就万事大吉,实际项目里真正摧毁业务体验的往往是后三者。
2.1 带宽:只是起点,不是全部
带宽指单位时间内链路能传输的数据量,是 QoS 最直观的资源。带宽保障有两种口径:保证带宽和最大带宽。前者是 QoS 承诺给某类流量至少能拿到的速率,后者是允许某类流量最多能到达的速率。注意,保证带宽并不意味着这条链路时刻都在用这么多,而是“当拥塞发生时,你仍然能拿到这么多”。很多刚接触 QoS 的同学把保证带宽当作持续速率来规划,结果预留总和超过物理带宽,策略一部署就开始丢包。
2.2 时延:端到端延迟的四个成分
时延指报文从源到目的地花费的时间。端到端时延由四部分构成:
- 处理时延:设备 CPU/芯片检查报文、查路由表的时间,现代硬件上极短。
- 排队时延:报文在设备出口队列中等待发送的时间。这是 QoS 能直接影响的部分。
- 传输时延:电磁波在介质上传播的时间,和物理距离正相关,光纤中约每百公里 0.5 毫秒,QoS 无能为力。
- 序列化时延:把报文比特逐一送上链路所需时间,由接口速率决定。速率越低,报文越大,序列化时延越长,这也是低带宽链路对语音影响更大的原因之一。
QoS 队列调度的目标,主要就是压缩关键流量的排队时延。语音业务通常要求单向时延低于 150 毫秒,超过这个值人耳就会明显感觉不自然。
2.3 抖动:音视频卡顿的隐形杀手
抖动是“时延的变化量”。即使平均时延很低,只要时延忽高忽低,语音和视频播放就会一卡一卡。原因是接收端的缓冲(Jitter Buffer)需要持续供数据,一旦某段数据晚到,缓冲耗尽,画面就停顿。QoS 的队列调度让关键流量获得稳定的服务,本质上是为了减小抖动,而不只是降低平均时延。
2.4 丢包:各种业务都有苦难言
丢包率是网络质量最直接的反映。对于 TCP 业务,丢包触发拥塞窗口减半,吞吐量断崖式下降;对于 UDP 音视频,丢包直接造成画面马赛克、语音断字。QoS 并不是“零丢包”,而是控制丢包发生的对象和时机——拥塞时优先丢不重要的报文,甚至提前丢,从而保护关键流量。
我经常在项目中把这四个指标比作快递服务:带宽是运力,时延是承诺时效,抖动是时效的稳定性,丢包是包裹损坏率。你做 QoS,本质是给不同客户承诺不同水平的快递服务。
3. 流量识别与标记:先认清谁是谁
所有 QoS 策略的前提是能区分报文。这一步做错,后面全错。流量识别的手段很多,对应不同的部署成本和精度。
3.1 分类的五种常用手段
- 接口/VLAN 分类:根据报文从哪个物理接口或哪个 VLAN 进来归类。优点是零额外成本,常用于边界:内部网络信任,外部网络不信任。
- MAC 地址分类:针对特定终端设备归类,适合打印机、IP 话机这类固定终端。
- IP 地址与五元组分类:根据源/目的 IP、协议号、源/目的端口归类。例如识别 SIP 信令的 5060 端口,识别 RTP 语音媒体流的端口范围。这是最常见的静态分类方式。
- DSCP 值分类:直接看报文头里携带的优先级标记。优点是能跨设备传递分类结果,缺点是前提是上游设备已正确打标。
- 深度报文检测(DPI):逐包检查应用层特征来识别应用,比如识别某个视频会议软件的流量。精度高,但消耗设备性能,通常只在网络边界做。
实际部署中我建议的次序是:接口属于哪一类、目的 IP 是不是核心服务器、端口是不是约定的关键应用端口、DSCP 是什么。从上往下用,成本递增,能不用 DPI 就不用。
3.2 优先级标记:DSCP、IP 优先级与 802.1p
分类之后要把结果标记到报文上,让下游设备能识别。IP 报文头里的 TOS 字节(Type of Service)被划分为 DS 字段,其中 6 比特是 DSCP 值(DiffServ Code Point),可定义 64 个类别。常用的 DSCP 约定包括:
- EF(Expedited Forwarding,101110):低时延低丢包,用于语音。
- AF(Assured Forwarding,AF1x-AF4x):保证转发类,分为四个等级,每个等级又有三个丢弃优先级,适用于视频、关键数据等。例如 AF41 表示最高等级、最低丢弃概率。
- CS(Class Selector):兼容旧的 IP 优先级值,CS3 等用于信令类流量。
在局域网二层,VLAN 标签里还有 3 比特的 802.1p 值,范围 0-7,用于交换机队列映射。典型映射中 6、7 给语音和控制、4、5 给视频、2-3 给关键数据、0 为尽力而为、1 为背景流量。
这里有个非常重要的设计原则:DSCP 值最好全网统一规划。很多网络乱在大家各打各的标——交换机到货默认值、不同业务部门自定义的 DSCP、厂商默认映射表都不一样,结果就是 QoS 策略“各说各话”,下游设备根本不知道该信任谁。
3.3 信任边界:在哪相信标记,在哪重新写
信任边界(Trust Boundary)是 QoS 设计最容易忽略的点。它的定义是:网络从哪个设备开始相信报文自带的优先级标记。PC、打印机这些终端完全可能被用户篡改标记,如果所有设备都无条件信任 DSCP 值,某个员工把本机所有流量都标成 EF,就能霸占整个网络的转发资源。
正确的做法是:接入交换机作为信任边界之后的第一个非信任点,对终端进来的流量按既定策略重新打标;往上到汇聚、核心层再信任 DSCP 值,做队列调度和拥塞管理。先打标再信任,不要一上来就全链路信任。我在一个项目里见过全员标 EF 的极端情况:某位同事发现给下载任务标 EF 后下载明显变快,后来全公司效仿,语音直接瘫痪。QoS 没有信任边界,就等于没设防。
4. 队列调度与拥塞管理:排队里的大学问
设备接口在出方向拥塞时,需要把报文放进队列,再由调度器决定“下一个发谁”。队列调度算法决定了关键流量能拿到多少资源、要等多久。
4.1 FIFO 不够用的原因
尽力而为模式默认就是一个 FIFO(先进先出)队列。优点是无脑、零开销;缺点是没有任何区分度,一个大数据流的持续发送会让其他所有流排在后面。更要命的是 FIFO 下队列充满后就是尾丢弃,所有流一起遭殃。
4.2 严格优先队列与自定义队列
严格优先队列(PQ)把所有流量按优先级放不同队列,调度时永远先清空高优先级队列。优点是高优先级流量时延极低;缺点是低优先级队列可能长期得不到服务,甚至被饿死,连管理协议报文、路由协议报文都可能发不出去。生产环境几乎不会用纯 PQ 处理数据流量,只会在局部小范围用。
自定义队列(CQ)把流量按类别分到最多 16 个队列,每个队列按配置的字节数轮询发送。优点是各类流量都有基本保障;缺点是配置繁琐,且轮询粒度是字节数,实时业务仍可能因为等待周期产生时延。
4.3 加权公平队列的思路
加权公平队列(WFQ)是经典算法:系统按会话(五元组)自动分流,每个会话一个队列,调度时按权重分配发送次数。它的好处是自动让每个活跃会话都“有口饭吃”,避免某个大流独占带宽;坏处是权重默认基于 IP 优先级,没法按业务自定义加权策略,也不能保证某类业务拿到指定带宽。
4.4 CBWFQ 与 LLQ:实际部署的主力
CBWFQ(基于类的加权公平队列)解决了分类问题:管理员先定义若干流量类别,为每个类别指定带宽比例或具体速率,调度时按比例向各类别分配发送机会。这已经能满足大多数组网需求,但它对实时流量还不够友好——语音要求的是“稳定低时延”,而不是“平均有带宽”。
于是 LLQ(低延迟队列)出现了。它的思路是:为语音等实时流量设置一个严格优先队列,同时用最大带宽限制防止其霸占链路。这样语音既获得近似物理直连的时延,又不会把其他业务全部饿死。LLQ 可以说是当前语音视频 QoS 配置中的核心。
下面这张表可以快速比较常见队列算法的特点:
| 算法 | 分类能力 | 是否保证带宽 | 实时业务友好度 | 实现复杂度 |
|---|---|---|---|---|
| FIFO | 无 | 无 | 差 | 最低 |
| PQ | 按优先级 | 高优先级占用全部 | 好但会饿死其他业务 | 低 |
| CQ | 手工分类 | 有 | 一般 | 中 |
| WFQ | 按会话自动 | 按权重公平 | 一般 | 低 |
| CBWFQ | 按业务类别 | 有 | 较好 | 中 |
| LLQ | 按业务类别 | 有 | 极好 | 中 |
我在实际配置中的经验是:语音走 LLQ,视频和关键交易数据走 CBWFQ 的保证带宽,其余流量走默认类(Default Class)共享剩余带宽。这样既保护了实时业务,又不至于让文件传输彻底断粮。
5. 拥塞避免:不等队列满了再丢
队列调度管的是“谁先走”,拥塞避免管的是“能不能别把所有流量一起拖死”。很多人以为 QoS 只是队列算法,实际上拥塞避免策略同样是核心环节。
5.1 尾丢弃引发的“全局同步”问题
尾丢弃发生在队列已满时。它的后果不只是丢几个报文那么简单:当队列持续满,TCP 流们几乎同时开始丢包,又几乎同时触发超时重传、同时把拥塞窗口减半,链路利用率瞬间跌到谷底;然后大家一起慢慢探测带宽,又一起把链路填满,再次进入循环。这种周期性的集体阵痛叫 TCP 全局同步,会显著降低整条链路的吞吐量。
5.2 RED:在队列满之前“敲打”发送端
RED(随机早期检测)的思路是:队列还没满时,就按一定概率随机丢弃部分报文,让部分 TCP 发送端提前降速。因为丢包是随机的,只有部分 TCP 流被“敲打”降速,链路总量平稳过渡,避免所有流一起崩溃。概率和队列平均长度挂钩——队列越长,丢弃概率越高。
RED 对 TCP 有效,对 UDP 基本没用,因为 UDP 不感知丢包也不降速。
5.3 WRED:让丢包也有优先级
WRED(加权随机早期检测)是 RED 的扩展:对不同 DSCP 值的报文设置不同丢弃曲线。例如高优先级的 AF41 报文的丢弃概率远低于低优先级的 AF21;即便最终必须丢,也是先丢不太重要的。这就是 QoS 里“有计划的牺牲”——拥塞不可避免时,主动选择牺牲哪些流量。
部署 WRED 时要注意一个关键点:它必须配合足够大的队列缓冲才有意义。队列太浅,RED 还没来得及“提前丢”,队列已经满了,算法退化成尾丢弃。我见过有人把接口队列深度调到最低以降低时延,结果 WRED 完全失效,还误以为是算法有问题。
6. 流量限速与整形:令牌桶的两种玩法
队列和拥塞避免解决的是“发送顺序”,但有些场景必须控制“流量的速率上限”。比如大型下载占满出口带宽时,你希望它只走 50Mbps,剩下留给关键业务。这就是流量限速(Policing)和流量整形(Shaping),两者的核心机制都是令牌桶。
6.1 令牌桶的基本原理
令牌桶有两个参数:承诺信息速率(CIR)——每秒往桶里放多少个令牌;承诺突发尺寸(CBS)——桶的最大容量。一个报文要通过,必须从桶里拿走对应字节数的令牌:桶里有令牌才能放行,没令牌就得等或丢弃。
这个机制的精妙之处在于它允许一定突发。如果链路空闲,桶会慢慢被令牌填满;突然来了一批报文,即使超过 CIR,只要桶里还有积攒的令牌,也可以一次性通过。所以 CIR 不是“瞬时速度上限”,而是“长期平均速率的上限”,CBS 决定了你能缓冲多少突发流量。
6.2 限速和整形是完全两回事
限速(Policing)发生在入方向(最常见,也可以用在出方向),超过令牌配额的报文直接丢弃,优点是响应快、不引入额外时延,缺点是可能把突发流量一刀切丢。
整形(Shaping)发生在出方向,超过令牌配额的报文先放进发送缓冲排队,等令牌够了再发。它不会丢关键报文,能把流量“抹平”成比较平滑的流,缺点是引入排队时延——对实时语音并不友好。
打个比方:限速是安检口直接拒绝超员乘客;整形是把超额乘客先请进候车厅,等下一趟车发。两种场景用途不同:想保护链路避免超卖用限速;想把接口速率调整到低于物理速率、避免上游设备因突发丢包,用整形。
6.3 双速率三色:进阶版管制
更复杂的场景使用双速率三色标记器(srTCM):维护 CIR、CBS 以及峰值速率 PIR、峰值突发 PBS 两套令牌桶。报文根据占用情况被标记为绿色、黄色或红色:
- 绿色:在 CIR 内,正常转发。
- 黄色:超过 CIR 但未超过 PIR,允许转发但在拥塞时先丢。
- 红色:超过 PIR,直接丢弃。
运营商网络和大型园区出口常用这种分层管制:同一个用户的 FTP 下载被压到保证速率以内,但允许瞬时突发,避免普通网页浏览被误伤。理解了 srTCM,你再看很多商业产品里“三色标记”功能就不会一头雾水了。
7. 从原理到落地:部署思路与验证心得
原理讲完,聊聊落地。QoS 部署失败的案例远比成功的多,原因往往不在算法,而在策略设计和验证方法上。
7.1 分层的部署策略
合理的 QoS 部署应该分层展开:
- 接入层:信任边界,负责对终端流量分类并打 DSCP 标记。
- 汇聚/核心层:信任 DSCP,执行队列调度、拥塞避免、带宽保证。
- 出口边界:执行限速/整形,防止园区流量超卖运营商带宽。
一个常见错误是“只在核心设备配了队列策略,但接入层没做任何标记”。核心设备看到的全是 DSCP=0 的尽力而为流量,策略根本无从区分。QoS 是端到端的设计,链路中任何一个环节放弃,效果就归零。
7.2 部署示例:从分类到策略映射
下面用接近业界主流设备的配置思维,展示一个语音 + 关键数据 + 尽力而为的典型层次。不同厂商的命令关键字略有差异,但大体都分为流分类、流策略、接口应用三步。
# 第一步:定义流量类别 流量类别 Voice 匹配 DSCP EF 匹配 UDP 目的端口范围 16384~32767 # 常见语音媒体端口 流量类别 Mission-App 匹配 DSCP AF41 匹配 目的 IP 地址组 核心数据库服务器地址 # 第二步:定义策略,对各类别施加行为 流量策略 QoS-Policy 类别 Voice 低延迟队列 带宽 1024 kbps # 语音走严格优先队列并限速 类别 Mission-App 保证带宽 30 % # 关键数据预留 30% 启用 WRED 按 DSCP 丢弃 # 拥塞时优先保护高优先级 默认类别 公平队列 剩余带宽 # 其他流量按会话公平分配 # 第三步:应用到接口出方向 接口 GigabitEthernet1/0/1 出方向 应用流量策略 QoS-Policy这段配置骨架的关键是:必须先想清楚每个类别的目标——语音要低时延所以进 LLQ,数据库交互要保证带宽所以要预留,普通下载要公平但不抢资源所以走默认类。策略只是思路的表达,思路错了配置再漂亮也没用。
7.3 验证方法:别拿 ping 当 QoS 测试工具
很多朋友配置完 QoS,直接点击测试连通性看时延是否下降,这个方法基本无效。QoS 只在拥塞时才发挥作用——空闲链路上所有流量都畅通,策略体现不出差别。正确验证分四步:
- 制造拥塞:在测试链路同时用多台机器发起大流量下载,让接口出方向持续满载。
- 观察队列统计:查看设备接口的队列深度、各类别丢包计数,确认关键类别的丢弃明显更少。
- 跑一次真实业务:用视频会议软件拨一场测试会议,在拥塞状态下观察画面和语音质量,而不是只看数字。
- 反向验证:临时把所有流量都标成 EF,再观察是否出现异常占用——确认信任边界和默认类兜底是否有效。
最后说几个我踩过的坑。第一,不要给所有业务都设“高优先级”,优先级是稀缺资源,全员优先等于无人优先。第二,队列带宽总预留不宜超过物理带宽的 75%,要给控制平面和突发留余地。第三,无线环境与有线完全不同,802.11 的介质竞争还需要专门机制配合,不要指望有线侧队列策略能直接解决无线终端的体验问题。第四,QoS 做成后一定要写文档:哪些 DSCP 给谁、信任边界在哪、接口方向是什么,否则三个月后没人记得当初的顺序,改一处配置就可能全线翻车。