关于拥塞控制的几点思考
引言
拥塞控制要解决的根本问题,表述起来很简单:多个发送方共享一条链路,如何协调各自的发送速率,使得链路资源被充分利用,同时避免因过载而崩溃。
但这个问题没有终极答案。它之所以难,不是因为数学不够精巧,而是因为它本质上是在不确定的环境中做决策。你所依赖的测量信号永远是不完整的,你所构建的模型永远是对现实的简化,你所能做的,永远是在多个互斥的目标之间寻找一个可接受的平衡。
下面从六个方面展开。
一、测量的互斥性
拥塞控制的第一步是测量链路状态。但这里存在一个根本性的互斥:
#mermaid-svg-6vg2ulqnSJrTwgkl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6vg2ulqnSJrTwgkl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6vg2ulqnSJrTwgkl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6vg2ulqnSJrTwgkl .error-icon{fill:#552222;}#mermaid-svg-6vg2ulqnSJrTwgkl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6vg2ulqnSJrTwgkl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6vg2ulqnSJrTwgkl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6vg2ulqnSJrTwgkl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6vg2ulqnSJrTwgkl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6vg2ulqnSJrTwgkl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6vg2ulqnSJrTwgkl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6vg2ulqnSJrTwgkl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6vg2ulqnSJrTwgkl .marker.cross{stroke:#333333;}#mermaid-svg-6vg2ulqnSJrTwgkl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6vg2ulqnSJrTwgkl p{margin:0;}#mermaid-svg-6vg2ulqnSJrTwgkl .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6vg2ulqnSJrTwgkl .cluster-label text{fill:#333;}#mermaid-svg-6vg2ulqnSJrTwgkl .cluster-label span{color:#333;}#mermaid-svg-6vg2ulqnSJrTwgkl .cluster-label span p{background-color:transparent;}#mermaid-svg-6vg2ulqnSJrTwgkl .label text,#mermaid-svg-6vg2ulqnSJrTwgkl span{fill:#333;color:#333;}#mermaid-svg-6vg2ulqnSJrTwgkl .node rect,#mermaid-svg-6vg2ulqnSJrTwgkl .node circle,#mermaid-svg-6vg2ulqnSJrTwgkl .node ellipse,#mermaid-svg-6vg2ulqnSJrTwgkl .node polygon,#mermaid-svg-6vg2ulqnSJrTwgkl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6vg2ulqnSJrTwgkl .rough-node .label text,#mermaid-svg-6vg2ulqnSJrTwgkl .node .label text,#mermaid-svg-6vg2ulqnSJrTwgkl .image-shape .label,#mermaid-svg-6vg2ulqnSJrTwgkl .icon-shape .label{text-anchor:middle;}#mermaid-svg-6vg2ulqnSJrTwgkl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6vg2ulqnSJrTwgkl .rough-node .label,#mermaid-svg-6vg2ulqnSJrTwgkl .node .label,#mermaid-svg-6vg2ulqnSJrTwgkl .image-shape .label,#mermaid-svg-6vg2ulqnSJrTwgkl .icon-shape .label{text-align:center;}#mermaid-svg-6vg2ulqnSJrTwgkl .node.clickable{cursor:pointer;}#mermaid-svg-6vg2ulqnSJrTwgkl .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6vg2ulqnSJrTwgkl .arrowheadPath{fill:#333333;}#mermaid-svg-6vg2ulqnSJrTwgkl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6vg2ulqnSJrTwgkl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6vg2ulqnSJrTwgkl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6vg2ulqnSJrTwgkl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6vg2ulqnSJrTwgkl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6vg2ulqnSJrTwgkl .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6vg2ulqnSJrTwgkl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6vg2ulqnSJrTwgkl .cluster text{fill:#333;}#mermaid-svg-6vg2ulqnSJrTwgkl .cluster span{color:#333;}#mermaid-svg-6vg2ulqnSJrTwgkl div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6vg2ulqnSJrTwgkl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6vg2ulqnSJrTwgkl rect.text{fill:none;stroke-width:0;}#mermaid-svg-6vg2ulqnSJrTwgkl .icon-shape,#mermaid-svg-6vg2ulqnSJrTwgkl .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6vg2ulqnSJrTwgkl .icon-shape p,#mermaid-svg-6vg2ulqnSJrTwgkl .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6vg2ulqnSJrTwgkl .icon-shape .label rect,#mermaid-svg-6vg2ulqnSJrTwgkl .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6vg2ulqnSJrTwgkl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6vg2ulqnSJrTwgkl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6vg2ulqnSJrTwgkl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 你想测量什么?
带宽
延迟
需要塞满链路
需要清空队列
塞满→排队→延迟被污染
清空→空闲→带宽测量失效
你永远无法同时获知
带宽和延迟的真值
这是一个观测困境。任何算法都必须在这个困境中选择一个优先方向:要么先测带宽,接受延迟测量暂时不可靠;要么先测延迟,接受带宽测量暂时不可靠。没有人能同时做到两件事。
这意味着,所有算法从第一步开始就已经带着偏见。
二、信号含义的模糊性
即使你获得了测量值,如何解读它也是一个难题。
#mermaid-svg-zzkeLlHFkCdNTt9L{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zzkeLlHFkCdNTt9L .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zzkeLlHFkCdNTt9L .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zzkeLlHFkCdNTt9L .error-icon{fill:#552222;}#mermaid-svg-zzkeLlHFkCdNTt9L .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zzkeLlHFkCdNTt9L .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zzkeLlHFkCdNTt9L .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zzkeLlHFkCdNTt9L .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zzkeLlHFkCdNTt9L .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zzkeLlHFkCdNTt9L .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zzkeLlHFkCdNTt9L .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zzkeLlHFkCdNTt9L .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zzkeLlHFkCdNTt9L .marker.cross{stroke:#333333;}#mermaid-svg-zzkeLlHFkCdNTt9L svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zzkeLlHFkCdNTt9L p{margin:0;}#mermaid-svg-zzkeLlHFkCdNTt9L .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zzkeLlHFkCdNTt9L .cluster-label text{fill:#333;}#mermaid-svg-zzkeLlHFkCdNTt9L .cluster-label span{color:#333;}#mermaid-svg-zzkeLlHFkCdNTt9L .cluster-label span p{background-color:transparent;}#mermaid-svg-zzkeLlHFkCdNTt9L .label text,#mermaid-svg-zzkeLlHFkCdNTt9L span{fill:#333;color:#333;}#mermaid-svg-zzkeLlHFkCdNTt9L .node rect,#mermaid-svg-zzkeLlHFkCdNTt9L .node circle,#mermaid-svg-zzkeLlHFkCdNTt9L .node ellipse,#mermaid-svg-zzkeLlHFkCdNTt9L .node polygon,#mermaid-svg-zzkeLlHFkCdNTt9L .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zzkeLlHFkCdNTt9L .rough-node .label text,#mermaid-svg-zzkeLlHFkCdNTt9L .node .label text,#mermaid-svg-zzkeLlHFkCdNTt9L .image-shape .label,#mermaid-svg-zzkeLlHFkCdNTt9L .icon-shape .label{text-anchor:middle;}#mermaid-svg-zzkeLlHFkCdNTt9L .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zzkeLlHFkCdNTt9L .rough-node .label,#mermaid-svg-zzkeLlHFkCdNTt9L .node .label,#mermaid-svg-zzkeLlHFkCdNTt9L .image-shape .label,#mermaid-svg-zzkeLlHFkCdNTt9L .icon-shape .label{text-align:center;}#mermaid-svg-zzkeLlHFkCdNTt9L .node.clickable{cursor:pointer;}#mermaid-svg-zzkeLlHFkCdNTt9L .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zzkeLlHFkCdNTt9L .arrowheadPath{fill:#333333;}#mermaid-svg-zzkeLlHFkCdNTt9L .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zzkeLlHFkCdNTt9L .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zzkeLlHFkCdNTt9L .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zzkeLlHFkCdNTt9L .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zzkeLlHFkCdNTt9L .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zzkeLlHFkCdNTt9L .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zzkeLlHFkCdNTt9L .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zzkeLlHFkCdNTt9L .cluster text{fill:#333;}#mermaid-svg-zzkeLlHFkCdNTt9L .cluster span{color:#333;}#mermaid-svg-zzkeLlHFkCdNTt9L div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zzkeLlHFkCdNTt9L .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zzkeLlHFkCdNTt9L rect.text{fill:none;stroke-width:0;}#mermaid-svg-zzkeLlHFkCdNTt9L .icon-shape,#mermaid-svg-zzkeLlHFkCdNTt9L .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zzkeLlHFkCdNTt9L .icon-shape p,#mermaid-svg-zzkeLlHFkCdNTt9L .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zzkeLlHFkCdNTt9L .icon-shape .label rect,#mermaid-svg-zzkeLlHFkCdNTt9L .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zzkeLlHFkCdNTt9L .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zzkeLlHFkCdNTt9L .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zzkeLlHFkCdNTt9L :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 可能的原因
观测
丢包
RTT增加
真拥塞
无线干扰
浅缓存
路由切换
调度抖动
自身突发
丢包是一个物理事实,但造成丢包的原因多种多样。把丢包当作拥塞信号,在无线网络或浅缓存场景下会导致不必要的降速;不把丢包当回事,在真正拥塞时又可能让队列无限增长。
RTT的增加同样模糊。一次路由切换可能让延迟永久增加几十毫秒,但这与拥塞无关。一次系统时钟抖动可能产生一个异常大的RTT样本,但下一毫秒就恢复正常。你无法仅从一个数字判断它背后的物理原因。
算法只能做一种假设:要么假定大多数异常是噪声,可以过滤;要么假定大多数异常是信号,需要响应。没有哪种假设永远正确。
三、利用率与拥塞的对立
算法的第一目标是带宽利用率------用户为带宽付费,自然希望用满它。但利用率与拥塞之间存在天然矛盾:
#mermaid-svg-ubugxRXkUgPV9cGo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ubugxRXkUgPV9cGo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ubugxRXkUgPV9cGo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ubugxRXkUgPV9cGo .error-icon{fill:#552222;}#mermaid-svg-ubugxRXkUgPV9cGo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ubugxRXkUgPV9cGo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ubugxRXkUgPV9cGo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ubugxRXkUgPV9cGo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ubugxRXkUgPV9cGo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ubugxRXkUgPV9cGo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ubugxRXkUgPV9cGo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ubugxRXkUgPV9cGo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ubugxRXkUgPV9cGo .marker.cross{stroke:#333333;}#mermaid-svg-ubugxRXkUgPV9cGo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ubugxRXkUgPV9cGo p{margin:0;}#mermaid-svg-ubugxRXkUgPV9cGo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ubugxRXkUgPV9cGo .cluster-label text{fill:#333;}#mermaid-svg-ubugxRXkUgPV9cGo .cluster-label span{color:#333;}#mermaid-svg-ubugxRXkUgPV9cGo .cluster-label span p{background-color:transparent;}#mermaid-svg-ubugxRXkUgPV9cGo .label text,#mermaid-svg-ubugxRXkUgPV9cGo span{fill:#333;color:#333;}#mermaid-svg-ubugxRXkUgPV9cGo .node rect,#mermaid-svg-ubugxRXkUgPV9cGo .node circle,#mermaid-svg-ubugxRXkUgPV9cGo .node ellipse,#mermaid-svg-ubugxRXkUgPV9cGo .node polygon,#mermaid-svg-ubugxRXkUgPV9cGo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ubugxRXkUgPV9cGo .rough-node .label text,#mermaid-svg-ubugxRXkUgPV9cGo .node .label text,#mermaid-svg-ubugxRXkUgPV9cGo .image-shape .label,#mermaid-svg-ubugxRXkUgPV9cGo .icon-shape .label{text-anchor:middle;}#mermaid-svg-ubugxRXkUgPV9cGo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ubugxRXkUgPV9cGo .rough-node .label,#mermaid-svg-ubugxRXkUgPV9cGo .node .label,#mermaid-svg-ubugxRXkUgPV9cGo .image-shape .label,#mermaid-svg-ubugxRXkUgPV9cGo .icon-shape .label{text-align:center;}#mermaid-svg-ubugxRXkUgPV9cGo .node.clickable{cursor:pointer;}#mermaid-svg-ubugxRXkUgPV9cGo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ubugxRXkUgPV9cGo .arrowheadPath{fill:#333333;}#mermaid-svg-ubugxRXkUgPV9cGo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ubugxRXkUgPV9cGo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ubugxRXkUgPV9cGo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ubugxRXkUgPV9cGo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ubugxRXkUgPV9cGo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ubugxRXkUgPV9cGo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ubugxRXkUgPV9cGo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ubugxRXkUgPV9cGo .cluster text{fill:#333;}#mermaid-svg-ubugxRXkUgPV9cGo .cluster span{color:#333;}#mermaid-svg-ubugxRXkUgPV9cGo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ubugxRXkUgPV9cGo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ubugxRXkUgPV9cGo rect.text{fill:none;stroke-width:0;}#mermaid-svg-ubugxRXkUgPV9cGo .icon-shape,#mermaid-svg-ubugxRXkUgPV9cGo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ubugxRXkUgPV9cGo .icon-shape p,#mermaid-svg-ubugxRXkUgPV9cGo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ubugxRXkUgPV9cGo .icon-shape .label rect,#mermaid-svg-ubugxRXkUgPV9cGo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ubugxRXkUgPV9cGo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ubugxRXkUgPV9cGo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ubugxRXkUgPV9cGo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 发送速率增加
队列增长
延迟增加
利用率接近上限
队列溢出
丢包
重传
有效吞吐下降
在达到瓶颈带宽之前,利用率随发送速率线性增长。越过瓶颈之后,额外流量只会增加队列长度和延迟,而不会提高有效吞吐。继续增加,队列溢出,丢包发生,重传消耗额外带宽,有效吞吐甚至可能下降。
所以,想跑满带宽,就必须接受一定程度的排队;想避免丢包,就必须牺牲一部分带宽。这不是算法缺陷,而是物理约束。
不同场景对这笔交易的接受度不同:
| 场景 | 偏好 | 策略 |
|---|---|---|
| 实时音视频 | 低延迟 | 宁可丢包也不排队 |
| 大文件传输 | 高吞吐 | 宁可排队也要压满 |
| 网页浏览 | 响应快 | 少量排队可接受,但不要丢包 |
没有一种策略能同时满足所有场景。
四、公平性的模糊边界
当多条流共享同一条链路时,算法还必须回答一个问题:谁应该得到多少?
#mermaid-svg-laTWXe05autJqByT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-laTWXe05autJqByT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-laTWXe05autJqByT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-laTWXe05autJqByT .error-icon{fill:#552222;}#mermaid-svg-laTWXe05autJqByT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-laTWXe05autJqByT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-laTWXe05autJqByT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-laTWXe05autJqByT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-laTWXe05autJqByT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-laTWXe05autJqByT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-laTWXe05autJqByT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-laTWXe05autJqByT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-laTWXe05autJqByT .marker.cross{stroke:#333333;}#mermaid-svg-laTWXe05autJqByT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-laTWXe05autJqByT p{margin:0;}#mermaid-svg-laTWXe05autJqByT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-laTWXe05autJqByT .cluster-label text{fill:#333;}#mermaid-svg-laTWXe05autJqByT .cluster-label span{color:#333;}#mermaid-svg-laTWXe05autJqByT .cluster-label span p{background-color:transparent;}#mermaid-svg-laTWXe05autJqByT .label text,#mermaid-svg-laTWXe05autJqByT span{fill:#333;color:#333;}#mermaid-svg-laTWXe05autJqByT .node rect,#mermaid-svg-laTWXe05autJqByT .node circle,#mermaid-svg-laTWXe05autJqByT .node ellipse,#mermaid-svg-laTWXe05autJqByT .node polygon,#mermaid-svg-laTWXe05autJqByT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-laTWXe05autJqByT .rough-node .label text,#mermaid-svg-laTWXe05autJqByT .node .label text,#mermaid-svg-laTWXe05autJqByT .image-shape .label,#mermaid-svg-laTWXe05autJqByT .icon-shape .label{text-anchor:middle;}#mermaid-svg-laTWXe05autJqByT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-laTWXe05autJqByT .rough-node .label,#mermaid-svg-laTWXe05autJqByT .node .label,#mermaid-svg-laTWXe05autJqByT .image-shape .label,#mermaid-svg-laTWXe05autJqByT .icon-shape .label{text-align:center;}#mermaid-svg-laTWXe05autJqByT .node.clickable{cursor:pointer;}#mermaid-svg-laTWXe05autJqByT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-laTWXe05autJqByT .arrowheadPath{fill:#333333;}#mermaid-svg-laTWXe05autJqByT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-laTWXe05autJqByT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-laTWXe05autJqByT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-laTWXe05autJqByT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-laTWXe05autJqByT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-laTWXe05autJqByT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-laTWXe05autJqByT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-laTWXe05autJqByT .cluster text{fill:#333;}#mermaid-svg-laTWXe05autJqByT .cluster span{color:#333;}#mermaid-svg-laTWXe05autJqByT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-laTWXe05autJqByT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-laTWXe05autJqByT rect.text{fill:none;stroke-width:0;}#mermaid-svg-laTWXe05autJqByT .icon-shape,#mermaid-svg-laTWXe05autJqByT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-laTWXe05autJqByT .icon-shape p,#mermaid-svg-laTWXe05autJqByT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-laTWXe05autJqByT .icon-shape .label rect,#mermaid-svg-laTWXe05autJqByT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-laTWXe05autJqByT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-laTWXe05autJqByT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-laTWXe05autJqByT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 折中
某种可接受的共存
每条流都感觉公平
总带宽未明显浪费
极端2
强制平均分配
所有流迁就最慢者
总带宽浪费
极端1
完全按需分配
强者恒强
小流可能被饿死
"公平"不是一个数学概念,而是一个社会性概念。不同用户、不同应用对公平的期待不同。TCP的"公平"通常指"各流平分瓶颈带宽",但这隐含了假设:所有流同等重要、同等持久、同等对延迟敏感。这些假设在现实中常常不成立。
一个诚实的表述是:我们无法定义绝对公平,只能定义一种可接受的共存状态------在这种状态下,没有一条流觉得自己被恶意压制,整体带宽没有被明显浪费。这个边界是模糊的,不同算法划在不同的位置。
五、测量工具的假设与局限
任何测量工具都带有假设。算法的差异,很大程度上是测量工具的差异。
#mermaid-svg-FDqSB51HGyQS0chq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FDqSB51HGyQS0chq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FDqSB51HGyQS0chq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FDqSB51HGyQS0chq .error-icon{fill:#552222;}#mermaid-svg-FDqSB51HGyQS0chq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FDqSB51HGyQS0chq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FDqSB51HGyQS0chq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FDqSB51HGyQS0chq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FDqSB51HGyQS0chq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FDqSB51HGyQS0chq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FDqSB51HGyQS0chq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FDqSB51HGyQS0chq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FDqSB51HGyQS0chq .marker.cross{stroke:#333333;}#mermaid-svg-FDqSB51HGyQS0chq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FDqSB51HGyQS0chq p{margin:0;}#mermaid-svg-FDqSB51HGyQS0chq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FDqSB51HGyQS0chq .cluster-label text{fill:#333;}#mermaid-svg-FDqSB51HGyQS0chq .cluster-label span{color:#333;}#mermaid-svg-FDqSB51HGyQS0chq .cluster-label span p{background-color:transparent;}#mermaid-svg-FDqSB51HGyQS0chq .label text,#mermaid-svg-FDqSB51HGyQS0chq span{fill:#333;color:#333;}#mermaid-svg-FDqSB51HGyQS0chq .node rect,#mermaid-svg-FDqSB51HGyQS0chq .node circle,#mermaid-svg-FDqSB51HGyQS0chq .node ellipse,#mermaid-svg-FDqSB51HGyQS0chq .node polygon,#mermaid-svg-FDqSB51HGyQS0chq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FDqSB51HGyQS0chq .rough-node .label text,#mermaid-svg-FDqSB51HGyQS0chq .node .label text,#mermaid-svg-FDqSB51HGyQS0chq .image-shape .label,#mermaid-svg-FDqSB51HGyQS0chq .icon-shape .label{text-anchor:middle;}#mermaid-svg-FDqSB51HGyQS0chq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FDqSB51HGyQS0chq .rough-node .label,#mermaid-svg-FDqSB51HGyQS0chq .node .label,#mermaid-svg-FDqSB51HGyQS0chq .image-shape .label,#mermaid-svg-FDqSB51HGyQS0chq .icon-shape .label{text-align:center;}#mermaid-svg-FDqSB51HGyQS0chq .node.clickable{cursor:pointer;}#mermaid-svg-FDqSB51HGyQS0chq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FDqSB51HGyQS0chq .arrowheadPath{fill:#333333;}#mermaid-svg-FDqSB51HGyQS0chq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FDqSB51HGyQS0chq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FDqSB51HGyQS0chq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FDqSB51HGyQS0chq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FDqSB51HGyQS0chq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FDqSB51HGyQS0chq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FDqSB51HGyQS0chq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FDqSB51HGyQS0chq .cluster text{fill:#333;}#mermaid-svg-FDqSB51HGyQS0chq .cluster span{color:#333;}#mermaid-svg-FDqSB51HGyQS0chq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FDqSB51HGyQS0chq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FDqSB51HGyQS0chq rect.text{fill:none;stroke-width:0;}#mermaid-svg-FDqSB51HGyQS0chq .icon-shape,#mermaid-svg-FDqSB51HGyQS0chq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FDqSB51HGyQS0chq .icon-shape p,#mermaid-svg-FDqSB51HGyQS0chq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FDqSB51HGyQS0chq .icon-shape .label rect,#mermaid-svg-FDqSB51HGyQS0chq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FDqSB51HGyQS0chq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FDqSB51HGyQS0chq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FDqSB51HGyQS0chq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 适用边界
隐含假设
测量方法
滑动窗口取最小值
卡尔曼滤波
AIMD/丢包反馈
噪声偶发
信号稳定
随机游走过程
高斯噪声
丢包是拥塞主信号
其他因素可忽略
低抖动网络
高噪声网络
需处理不确定性
浅缓存/无线场景
假设常被违反
滑动窗口取最小值,默认真实延迟是稳定的,噪声只是偶尔的异常。当网络频繁抖动或路径切换时,这个假设就会出问题。
卡尔曼滤波假设过程是随机游走、噪声是高斯分布。这个假设在很多场景下更贴近现实,但它仍然是简化------真实网络的噪声并不总是高斯的。
丢包作为拥塞信号的假设,在现代网络(大缓存、无线、数据中心)中越来越不可靠。
没有万能的测量工具。每个工具都有它的适用环境,而环境是会变的。
六、两种思想
面对上述所有不确定性,算法设计大致有两种思路。
#mermaid-svg-TeEVGWYOyYpXvgkQ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TeEVGWYOyYpXvgkQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TeEVGWYOyYpXvgkQ .error-icon{fill:#552222;}#mermaid-svg-TeEVGWYOyYpXvgkQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TeEVGWYOyYpXvgkQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TeEVGWYOyYpXvgkQ .marker.cross{stroke:#333333;}#mermaid-svg-TeEVGWYOyYpXvgkQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TeEVGWYOyYpXvgkQ p{margin:0;}#mermaid-svg-TeEVGWYOyYpXvgkQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TeEVGWYOyYpXvgkQ .cluster-label text{fill:#333;}#mermaid-svg-TeEVGWYOyYpXvgkQ .cluster-label span{color:#333;}#mermaid-svg-TeEVGWYOyYpXvgkQ .cluster-label span p{background-color:transparent;}#mermaid-svg-TeEVGWYOyYpXvgkQ .label text,#mermaid-svg-TeEVGWYOyYpXvgkQ span{fill:#333;color:#333;}#mermaid-svg-TeEVGWYOyYpXvgkQ .node rect,#mermaid-svg-TeEVGWYOyYpXvgkQ .node circle,#mermaid-svg-TeEVGWYOyYpXvgkQ .node ellipse,#mermaid-svg-TeEVGWYOyYpXvgkQ .node polygon,#mermaid-svg-TeEVGWYOyYpXvgkQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TeEVGWYOyYpXvgkQ .rough-node .label text,#mermaid-svg-TeEVGWYOyYpXvgkQ .node .label text,#mermaid-svg-TeEVGWYOyYpXvgkQ .image-shape .label,#mermaid-svg-TeEVGWYOyYpXvgkQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-TeEVGWYOyYpXvgkQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TeEVGWYOyYpXvgkQ .rough-node .label,#mermaid-svg-TeEVGWYOyYpXvgkQ .node .label,#mermaid-svg-TeEVGWYOyYpXvgkQ .image-shape .label,#mermaid-svg-TeEVGWYOyYpXvgkQ .icon-shape .label{text-align:center;}#mermaid-svg-TeEVGWYOyYpXvgkQ .node.clickable{cursor:pointer;}#mermaid-svg-TeEVGWYOyYpXvgkQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TeEVGWYOyYpXvgkQ .arrowheadPath{fill:#333333;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TeEVGWYOyYpXvgkQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TeEVGWYOyYpXvgkQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TeEVGWYOyYpXvgkQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TeEVGWYOyYpXvgkQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TeEVGWYOyYpXvgkQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TeEVGWYOyYpXvgkQ .cluster text{fill:#333;}#mermaid-svg-TeEVGWYOyYpXvgkQ .cluster span{color:#333;}#mermaid-svg-TeEVGWYOyYpXvgkQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TeEVGWYOyYpXvgkQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TeEVGWYOyYpXvgkQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-TeEVGWYOyYpXvgkQ .icon-shape,#mermaid-svg-TeEVGWYOyYpXvgkQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TeEVGWYOyYpXvgkQ .icon-shape p,#mermaid-svg-TeEVGWYOyYpXvgkQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TeEVGWYOyYpXvgkQ .icon-shape .label rect,#mermaid-svg-TeEVGWYOyYpXvgkQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TeEVGWYOyYpXvgkQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TeEVGWYOyYpXvgkQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TeEVGWYOyYpXvgkQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 设计哲学
规则驱动 Rule-based
模型驱动 Model-based
定义明确规则
增益、窗口、阈值
优点:行为可预测
易于实现和调试
缺点:规则不完备
总有未覆盖的 corner case
建立数学模型
用观测数据修正参数
优点:适应性强
可处理不确定性
缺点:模型假设偏差
误差可能被放大
规则驱动:写清楚if-then,规定什么时候增加窗口、什么时候减少。这种思路偏好确定性,行为可预测,调试方便。但它永远面临一个问题:规则无法穷尽所有情况。每发现一个新问题,就要打一个新补丁。补丁多了,系统变得脆弱且难以理解。
模型驱动:先假设网络行为可以用某个数学模型描述(比如随机游走、线性系统),然后用观测数据不断修正模型参数,最后根据模型输出做决策。这种思路更灵活,能适应环境变化。但它依赖于模型的正确性------如果模型假设偏离真实,误差会被迭代放大。
两种思路没有绝对优劣。它们只是对"不确定性"的不同态度:一种试图通过规则来控制它,另一种试图通过模型来量化它。
结语
拥塞控制不是一个可以 "终结" 的问题。
网络在变,应用在变,硬件在变,人们对 "好" 的定义也在变。一个在今天看来优雅的模型,明天可能因为新的场景而显得简陋。
一个诚实的拥塞控制算法设计者会说:我不知道最优解是什么。我只能选择一个不太坏的妥协。选择激进,就承受丢包;选择保守,就承受浪费;选择公平,就承受效率损失;选择效率,就承受不公平。
承认这个局限与自己的无知,可能比发明一个"完美"算法更重要。
因为说到底,我们是在用有限的观测、有偏的假设、互斥的目标,去应对一个我们永远无法完全了解的世界。这不是技术问题,这是认识论问题。
这篇博客没有结论,因为本来就没有结论。