HTB (Hierarchical Token Bucket)
HTB(Hierarchical Token Bucket,分层令牌桶)是 RouterOS 中的一种排队规则,用于速率限制和突发处理,它使用令牌桶算法以可配置的容量和限制来管理数据速率。
HTB(Hierarchical Token Bucket)
简介
HTB(Hierarchical Token Bucket,分层令牌桶)是一种带类别的排队规则,适用于速率限制和突发处理。本文仅聚焦 RouterOS 中与 HTB 相关的这些方面,因为我们使用了一个修改版本来实现 Simple Queue 和 Queue Tree 等功能。
令牌桶算法(图中红色部分)
令牌桶算法基于一个类比:一个桶中会以特定速率添加以字节表示的令牌,桶本身具有指定容量。
如果桶已装满到容量上限,新到达的令牌将被丢弃。
桶容量 = bucket-size * max-limit
- bucket size(0..10,默认值:0.1)
在允许任何数据包通过队列之前,会检查队列桶当时是否已包含足够的令牌。
如果是,则移除(“兑现”)相应数量的令牌,并允许该数据包通过队列。
如果不是,数据包会停留在数据包等待队列的开头,直到有足够的令牌可用。
在多级队列结构的情况下,子队列中使用的令牌也会“计入”其父队列。换句话说,子队列从父队列“借用”令牌。
数据包队列(图中蓝色部分)
该数据包队列的大小、顺序、数据包如何加入此队列以及何时丢弃数据包,由以下因素决定:
- queue-type - Queue
- queue-size - Queue Size
令牌速率选择(图中黑色部分)
任意时刻的最大令牌速率等于以下值中最高的活动值:
- limit-at(NUMBER/NUMBER):保证给某个目标的 上传/下载 数据速率。
- max-limit(NUMBER/NUMBER):允许给某个目标的最大 上传/下载 数据速率。
- burst-limit(NUMBER/NUMBER):“突发”处于活动状态时允许给某个目标的最大 上传/下载 数据速率。
burst-limit 仅在“突发”处于允许状态时生效——更多信息见:Queue Burst
当 limit-at 是最高的值时,需要额外发放令牌,以补偿所有未能从父队列借用的缺失令牌。
示意图

桶大小实战
让我们用一个简单的设置,将来自和去往某个 IP 地址的所有流量都标记为 packet-mark:
/ip/firewall/mangle
add chain=forward action=mark-connection connection-mark=no-mark src-address=192.168.88.101 new-connection-mark=pc1_conn
add chain=forward action=mark-connection connection-mark=no-mark dst-address=192.168.88.101 new-connection-mark=pc1_conn
add chain=forward action=mark-packet connection-mark=pc1_conn new-packet-mark=pc1_traffic
默认队列桶
/queue/tree
add name=download parent=Local packet-mark=pc1_traffic max-limit=10M
add name=upload parent=Public packet-mark=pc1_traffic max-limit=10M
在这种情况下,bucket-size=0.1,因此 bucket-capacity= 0.1 x 10M = 1M。
如果桶已满(也就是说,客户端有一段时间没有使用队列的全部容量),那么接下来 1Mb 的流量可以不受限制的速度通过队列。
大队列桶
/queue/tree
add name=download parent=Local packet-mark=pc1_traffic max-limit=10M bucket-size=10
add name=upload parent=Public packet-mark=pc1_traffic max-limit=10M bucket-size=10
让我们尝试把同样的逻辑应用到桶大小取最大值的情况:
在这种情况下,bucket-size=10,因此 bucket-capacity= 10 x 10M = 100M。
如果桶已满(也就是说,客户端有一段时间没有使用队列的全部容量),那么接下来 100Mb 的流量可以不受限制的速度通过队列。
所以你可以得到:
- 20Mbps 的传输速度持续 10 秒。
- 60Mbps 的传输突发持续 2 秒。
- 1Gbps 的传输突发持续约 100ms。
因此你可以看到,桶允许通过队列的流量具有某种“突发性”。该行为类似于普通的 burst 功能,但缺少 burst 的上限。如果我们在队列结构中利用桶大小,就可以避免这一缺陷:
大的子队列桶、小的父队列桶
/queue/tree
add name=download_parent parent=Local max-limit=20M
add name=download parent=download_parent packet-mark=pc1_traffic max-limit=10M bucket-size=10
add name=upload_parent parent=Public max-limit=20M
add name=upload parent=upload_parent packet-mark=pc1_traffic max-limit=10M bucket-size=10
在这种情况下:
- 父队列 bucket-size=0.1,bucket-capacity= 0.1 x 20M = 2M
- 子队列 bucket-size=10,bucket-capacity= 10 x 10M = 100M
父队列的令牌会比子队列更快耗尽,而由于其子队列总是从父队列借用令牌,整个系统将受限于父队列的令牌速率——在本例中为 max-limit=20M。该速率会一直维持到子队列的令牌耗尽,然后才会被限制到其 10Mbps 的令牌速率。
这样,我们就可以实现最高 20Mbps、最长 10 秒的突发。
配置
要创建 HTB,我们必须遵循三个基本步骤:
- 匹配并标记流量 —— 对流量进行分类以供后续使用。它由一个或多个匹配参数组成,用于为特定类别选择数据包。
- 创建标记流量的规则(策略) —— 将特定流量类别放入特定队列,并定义对每个类别执行的动作。
- 为特定接口附加策略 —— 为所有接口(global-in、global-out 或 global-total)、特定接口或特定父队列附加策略。
HTB 允许创建分层队列结构,并确定队列之间的关系,例如“父子”或“子子”。
一旦某个队列至少有一个子队列,它就变成一个 inner 队列。所有没有子队列的队列都是 leaf 队列。Leaf 队列进行实际的流量消耗,Inner 队列只负责流量分配。所有 leaf 队列都被平等对待。
在 RouterOS 中,必须指定 parent 选项才能将某个队列作为子队列分配给另一个队列。
双重限制
HTB 中的每个队列都有两个速率限制:
- CIR(Committed Information Rate,承诺信息速率)——(RouterOS 中的 limit-at)最坏情况场景,无论如何该流都将获得此数量的流量(假设我们确实能发送这么多数据)。
- MIR(Maximal Information Rate,最大信息速率)——(RouterOS 中的 max-limit)最好情况场景,如果其队列的父队列有空闲带宽,该流可以达到的速率。
换句话说,首先会满足所有队列的 limit-at(CIR),然后子队列才会尝试从父队列借用所需的数据速率,以达到其 max-limit(MIR)。
警告
CIR 将无条件分配给对应的队列(即使父队列的 max-limit 已被超出)。
因此,为确保以最优方式(如设计那样)使用双重限制功能,我们建议遵循以下规则:
- 所有子队列承诺速率之和必须小于或等于父队列可用的流量;
CIR(parent)* ≥ CIR(child1) +...+ CIR(childN)* 如果 parent 是主父队列,则 CIR(parent)=MIR(parent)
- 任何子队列的最大速率必须小于或等于父队列的最大速率。
MIR (parent) ≥ MIR(child1) & MIR (parent) ≥ MIR(child2) & ... & MIR (parent) ≥ MIR(childN)
Winbox 中的队列颜色
- 已使用可用流量的 0% - 50% —— 绿色
- 已使用可用流量的 50% - 75% —— 黄色
- 已使用可用流量的 75% - 100% —— 红色
优先级
我们已经知道,所有队列的 limit-at(CIR)都将无条件发放。
优先级负责将父队列剩余的流量分配给子队列,使它们能够达到 max-limit。
优先级较高的队列会先于优先级较低的队列达到其 max-limit。8 是最低优先级,1 是最高优先级。
请注意,优先级仅在以下情况下生效:
- 对于 leaf 队列——inner 队列中的优先级没有意义。
- 如果指定了 max-limit(不为 0)。
示例
在本节中,我们将分析 HTB 的实际运行。为此,我们将采用一个 HTB 结构,并通过改变 HTB 需要处理的传入流量以及更改一些选项,尽量覆盖所有可能的情况和功能。
结构
我们的 HTB 结构将由 5 个队列组成:
- Queue01 inner 队列,有两个子队列——Queue02 和 Queue03
- Queue02 inner 队列,有两个子队列——Queue04 和 Queue05
- Queue03 leaf 队列
- Queue04 leaf 队列
- Queue05 leaf 队列
Queue03、Queue04 和 Queue05 是需要始终拥有 10Mbps 的客户端。出接口能够处理 10Mbps 的流量。
示例 1:常见情况

- Queue01 limit-at=0Mbps max-limit=10Mbps
- Queue02 limit-at=4Mbps max-limit=10Mbps
- Queue03 limit-at=6Mbps max-limit=10Mbps priority=1
- Queue04 limit-at=2Mbps max-limit=10Mbps priority=3
- Queue05 limit-at=2Mbps max-limit=10Mbps priority=5
示例 1 的结果
- Queue03 将获得 6Mbps。
- Queue04 将获得 2Mbps。
- Queue05 将获得 2Mbps。
- 说明: HTB 的构建方式是,满足所有 limit-at 后,主队列不再有可分配的吞吐量。
示例 2:带 max-limit 的常见情况

- Queue01 limit-at=0Mbps max-limit=10Mbps
- Queue02 limit-at=4Mbps max-limit=10Mbps
- Queue03 limit-at=2Mbps max-limit=10Mbps priority=3
- Queue04 limit-at=2Mbps max-limit=10Mbps priority=1
- Queue05 limit-at=2Mbps max-limit=10Mbps priority=5
示例 2 的结果
- Queue03 将获得 2Mbps。
- Queue04 将获得 6Mbps。
- Queue05 将获得 2Mbps。
- 说明: 满足所有 limit-at 后,HTB 将把吞吐量分配给优先级最高的队列。
示例 3:Inner 队列的 limit-at

- Queue01 limit-at=0Mbps max-limit=10Mbps。
- Queue02 limit-at=8Mbps max-limit=10Mbps。
- Queue03 limit-at=2Mbps max-limit=10Mbps priority=1。
- Queue04 limit-at=2Mbps max-limit=10Mbps priority=3。
- Queue05 limit-at=2Mbps max-limit=10Mbps priority=5。
示例 3 的结果
- Queue03 将获得 2Mbps。
- Queue04 将获得 6Mbps。
- Queue05 将获得 2Mbps。
- 说明: 满足所有 limit-at 后,HTB 将把吞吐量分配给优先级最高的队列。但在本例中,inner 队列 Queue02 指定了 limit-at,这样做为队列 Queue04 和 Queue05 预留了 8Mbps 的吞吐量。在这两者中,Queue04 的优先级最高,因此它获得了额外的吞吐量。
示例 4:Leaf 队列的 limit-at

- Queue01 limit-at=0Mbps max-limit=10Mbps。
- Queue02 limit-at=4Mbps max-limit=10Mbps。
- Queue03 limit-at=6Mbps max-limit=10Mbps priority=1。
- Queue04 limit-at=2Mbps max-limit=10Mbps priority=3。
- Queue05 limit-at=12Mbps max-limit=15Mbps priority=5。
示例 4 的结果
- Queue03 将获得约 3Mbps。
- Queue04 将获得约 1Mbps。
- Queue05 将获得约 6Mbps。
- 说明: 仅仅为了满足所有 limit-at,HTB 就被迫分配 20Mbps——6Mbps 给 Queue03,2Mbps 给 Queue04,12Mbps 给 Queue05,但我们的出接口只能处理 10Mbps。由于出接口队列通常是 FIFO,吞吐量分配将保持 6:2:12 即 3:1:6 的比例。