认识 bufferbloat

很多人并不理解 bufferbloat 的本质,我引用《计算机网络-自顶向下方法(第 8 版)》第四章的一个解释:
在这里插入图片描述

很形象的比喻,buffer 就像盐,不可或缺,适量增味,过量食物就不能吃了。高血压患者更有所感受,一旦摄入过量盐,排盐就不是大量喝水能解决的了。

一旦 buffer 里堆满了数据包,它们就很难排空了,特别是在 aimd 这种 capacity-seeking 的作用力下,下面水流的例子更为直观:
在这里插入图片描述

虽然流速一直保持为 v,但相比下图,水流在上图的宽敞处会减慢流速而造成时延增大,如果上游不主动减小流量,水库是不会排空的。

bbr 解决 bufferbloat 之道有两个方法:

  • 从模型上保证 inflight 收敛到 bdp;
  • 定时 probertt 排空 queue,确保基础 rtt。

为了直观看到这个事实,将模型具象化是高尚的,作为对比,单流 bbr 的 inflight 模型非常简单,设 x 为 bbr 单流 inflight,C 为瓶颈带宽,R 为传播时延,方程如下:

d x d t = C ⋅ R − x \dfrac{dx}{dt}=C\cdot R-x dtdx=CRx

这是一个典型的负反馈模型,当 x 大于 bdp,inflight 要减小,避免 bufferbloat,当 x 小于 bdp,inflight 要增大,提高带宽利用率。可见,bbr 专为解决 bufferbloat 而生,inflight 就是 bdp。
而 aimd 则是一个 bufferbloat 制造者模型,以下是一个 “连续 md” 的示例:

beta = 0.5
C, R = 50, 2

# x, z 分别为两条流的 cwnd
def dxdt(x, y, t):
    if y > 0:
        return - beta * x
    else:
        return 1

def dzdt(z, y, t):
    if y > 0:
        return - beta * z
    else:
        return 1

def ydt(a, b, t):
    buff = 2 * C * R
    if (a + b) > buff:
        return 1
    elif False and (a + b) > (buff - int(buff / 4)):
        ret = 2*random.random() - 1
        return ret
    return 0

t = np.linspace(0, 800, 8000)
x = np.zeros_like(t)
y = np.zeros_like(t)
z = np.zeros_like(t)

x[0], z[0] = 1, 250

for i in range(1, len(t)):
    dt = t[i] - t[i - 1]
    dxy = ydt(x[i - 1], z[i - 1], i)
    dzy = ydt(z[i - 1], x[i - 1], i)
    dx = dxdt(x[i - 1], dxy, t[i - 1])
    dz = dzdt(z[i - 1], dzy, t[i - 1])
    x[i] = x[i - 1] + (dx) * dt
    z[i] = z[i - 1] + (dz) * dt

下图可看出,n 条流的 inflight 之和收敛到 bdp + buffer:
在这里插入图片描述

RED 版本结果如下:
在这里插入图片描述

buffer 占量降低了,但带宽利用率是代价。

为了快速收敛,避免拥塞加剧,实践中采用离散 md,即经典的锯齿:

for i in range(1, len(t)):
    dt = t[i] - t[i - 1]
    dy = ydt(x[i - 1], y[i - 1], i)
    dx = dxdt(x[i - 1], dy, t[i - 1])
    dz = dzdt(z[i - 1], dy, t[i - 1])
    if dy > 0:
        x[i] = x[i-1] * (1 - beta)
    else:
        x[i] = x[i - 1] + (dx) * dt

这一次我直接用 bbr 和离散 aimd 对比。bbr 的仿真实现非常简单:

def dzdt(z, y, t):
    if y > 0: # 模拟 bbr 不完备实现,丢包时数据包守恒
        return 0
    inflt = C * R - z
    return inflt

下图是没有 RED aimd 支持的:
在这里插入图片描述

可见,aimd 不达 bdp + buffer 不罢休,而 bbr 止步于 bdp。这意味着,有多大 buffer,aimd 用多大 buffer,buffer 越大,时延越大,这就是 bufferbloat 的恶果。

RED 轻微缓解了这个问题,但也不很:
在这里插入图片描述

多流 bbr 场景,n 条 bbr 流的 inflight 之和收敛到 bdp + probe_size,多日之前我用微分方程建模 bbr 时说过这事(从微分方程组构建 bbr 模型):
在这里插入图片描述

浙江温州皮鞋湿,下雨进水不会胖。

  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值