我读过很多次关于Linux的令牌桶过滤器(tbf)而且我仍然不完全明白应该如何计算burst
和latency
参数,对我来说很羞耻:(
我认为合理的延迟约为 50 毫秒。好的,但是burst 应该取什么值呢?
手册页说:
后者的计算考虑了桶的大小、速率以及可能的峰值速率(如果设置)。这两个参数是互斥的。
那么,延迟与存储桶和过滤器有何关系?有公式可以计算吗?或者这只是一个问题,“好吧,X 字节的突发和 Y 秒的延迟对我来说有好处”?
答案1
从联机帮助页来看,唯一的限制burst
是它必须足够高以允许您配置的速率:它必须至少为速率/HZ。 HZ是内核配置参数;您可以通过检查内核配置来了解系统上的内容。例如,在 Debian 上,您可以:
$ egrep '^CONFIG_HZ_[0-9]+' /boot/config-`uname -r`
CONFIG_HZ_250=y
所以我系统上的 HZ 是 250。要达到 10mbps 的速率,我需要burst
至少 10,000,000 位/秒 ÷ 250 Hz = 40,000 位 = 5000 字节。 (请注意,手册页中的较高值来自默认值 HZ=100 的情况)。
但除此之外,burst
也是一种政策工具。它配置您现在可以使用较少带宽的程度,以“保存”以供将来使用。这里的一个常见问题是,您可能希望允许小量下载(例如网页)运行得非常快,同时限制大下载。您可以通过增加到burst
您认为较小的下载大小来实现此目的。 (不过,您经常会切换到 htb 这样的有类 qdisc,这样您就可以划分出不同的流量类型。)
因此:您将突发配置为至少足够大以实现所需的rate
。除此之外,您还可以进一步增加它,具体取决于您想要实现的目标。
令牌桶过滤器的概念模型
“桶”是一个隐喻的物体。它的关键特性是它可以容纳代币,而且它可以容纳的代币数量是有限的——如果你尝试添加更多代币,它就会“溢出”,多余的代币就会丢失(就像试图在一个容器中放入太多的水一样)。实际桶)。桶的大小称为burst
。
为了实际将数据包传输到网络上,该数据包必须获得等于其大小(以字节为单位)或mpu
(以较大者为准)的令牌。
有(或可能有)一排(队列)数据包正在等待令牌。当桶为空或者令牌少于数据包大小时,就会发生这种情况。桶前面的人行道上只有这么多空间,空间量(以字节为单位)直接由 设定limit
。或者,它可以间接设置latency
(在理想世界中,计算结果为rate
× latency
)。
当内核想要将数据包发送出已过滤的接口时,它会尝试将数据包放置在行尾。如果人行道上没有任何空间,这对于数据包来说是不幸的,因为人行道的尽头是一个无底洞,内核会丢弃数据包。
最后一部分是一个代币制造机,它在每个周期都会将rate
/HZ
代币添加到桶中。 (这就是为什么你的桶必须至少这么大,否则一些新创建的令牌将立即被丢弃)。
答案2
另一个补充德罗伯特的答案。
首先,对于现代 Intel CPU,该手册已经过时。现代 CPU 具有高分辨率定时器,而现代 Linux 则没有滴答声 - 字面意思是没有定时器滴答声。因此,所有那些使存储桶足够大以在一个计时器中容纳令牌的评论都是无关紧要的。事实上,桶类比只是为了帮助用户理解计时器粒度和发送速度之间的相互作用。现在 Linux 在现代硬件上有了纳秒定时器,它就失去了它的用处。
对于TBF爆裂参数是在速率限制之前可以不限速发送的字节数(由速度)开始生效。一旦速率限制生效,再次爆发的唯一方法是将您的发送限制在该速率以下。
例如,假设您的 tbf爆裂参数是10K字节,你的tbf速度参数为 2K 字节/秒,并且您当前受到速率限制(即突发已耗尽,因此您只能以 2kbps 的速度发送)。如果您自愿将发送速度降低至 1Kbps 10 秒,您将再次累积 10K 字节突发限额(= (2000 [字节/秒] - 1000 [字节/秒]) * 10 秒)。将其保持在 1kbps 以下超过 10 秒将不会产生任何效果,因为 tbf 不允许您累积超过爆裂范围。
如果您完全停止支出,那么您将在 5 秒内再次获得突发津贴(= 100000 [字节] / 2000 [字节/秒])。
您无需将所有突发津贴取回即可使用,您可以使用累积的金额。
另一种看待这个问题的方式是:您可以发送爆裂无限速度字节,此后您的长期平均速度永远不会超过速度。但是,由于它是长期平均值,如果低于速度你可以通过全速发送来赶上 - 但即便如此,你最多也只能全速发送爆裂字节(如果这不允许你赶上你就不能)。
另一个问题是 TBF 有二这些速率限制器,并且您的流量必须通过这两个速率限制器。在第二个中,突发参数称为最大传输单元并且,该速率称为峰值速率。您应该使用第二个来限制第一个可以发送突发的速度。使用第二个是可选的,如果您不使用它,突发将以设备速度发送。
最后,tbf 有一个限制范围。如果程序持续发送速度快于速度,然后数据包将在队列中堆积。没有无限的内核内存,所以限制表示在内核开始丢弃数据包之前可以建立多少字节。