参见 Wi-Fi弱网传输优化不成功有感
早在几年前还做传输优化时,我就非常不赞同在弱网环境激进传输的优化策略,我一直觉得这是在劣化传输,这观点一直影响着我,我也屡次因为这个与经理发生冲突。这观点如下表述:
- 弱网环境用保守策略,保时延而不是赌带宽;
- 好的网络用激进策略,夺带宽同时赌时延。
弱网传输优化一直是从顶会到会议室争论的焦点,但所出之策全都纯属屎上雕花,就好比在教你如何用五菱宏光在颠簸的乡道开出 120 码的时速一样,本身就是弱网,难以预测,若难以预测,两个办法,一就是不预测,二就是保守预测,问题就解了,剩余的钱财和精力买更好的设备,升级网络则已。
弱网不能优化,弱网只能升级,而传输协议跟着随行。以下简单分析。
设每次传输数据量为 M,丢包率 p,带宽为 C,则成功传输一次的概率为 1 - p,根据伯努利试验几何分布推导,传输 M 直到成功的次数为
1
1
−
p
\dfrac{1}{1-p}
1−p1,所以总传输时间
T
=
M
C
⋅
(
1
−
p
)
T=\dfrac{M}{C\cdot(1-p)}
T=C⋅(1−p)M,定义传输效能:
E = C T = C 2 ⋅ ( 1 − p ) M E=\dfrac{C}{T}=\dfrac{C^2\cdot(1-p)}{M} E=TC=MC2⋅(1−p)
但做传输优化的小经理们均青睐激进策略(比如每报文发多遍),我在此将此行为泛化,不区分原数据和重传,仅将激进刻画为传输 “重复数据”,旨在快速恢复丢包或冗余防丢包,无论如何,激进行为占据了部分有效带宽,设激进程度为 r,则有效带宽 C ′ = C ⋅ ( 1 − k r ) C'=C\cdot(1-kr) C′=C⋅(1−kr),而一次成功传输的概率变为 1 - p*(1 - r),传输到成功的次数为 1 1 − p ⋅ ( 1 − r ) \dfrac{1}{1-p\cdot(1-r)} 1−p⋅(1−r)1,传输时间变为 T = M C ⋅ ( 1 − k r ) ⋅ ( 1 − p ⋅ ( 1 − r ) ) T=\dfrac{M}{C\cdot(1-kr)\cdot(1-p\cdot(1-r))} T=C⋅(1−kr)⋅(1−p⋅(1−r))M,加入 r 后的传输效能:
E = M T = C 2 ⋅ ( 1 − k r ) 2 ⋅ ( 1 − p ⋅ ( 1 − r ) ) M E=\dfrac{M}{T}=\dfrac{C^2\cdot(1-kr)^2\cdot(1-p\cdot(1-r))}{M} E=TM=MC2⋅(1−kr)2⋅(1−p⋅(1−r))
对 E 求关于 r 的偏导可获得 r 和 p 的关系对 E 大小的影响,但从 gif 图上看更直观:
由是观之,在 p 比较大时,激进程度 r 会带来正向影响,即快速恢复丢失的数据的同时,并不损失多少带宽,故 E 是递增的,而当 p 比较小时,激进程度只做一些无用功,无论如何 E 都会递减。
这看起来推翻了我自己的结论而不是证明,结论变成了 “若丢包率很高,激进会带来好处”。对,这就是直觉,但这是错觉。
到底哪里出了问题?
上述建模过程默认了一个前提,只要借用了带宽,就一定能恢复丢包,但这是不对的,明月光会射进沟渠,而不是你的真心。弱网并非均匀的等比兑换,均匀等比兑换的策略看这个:教你如何抢带宽,pixie。而弱网环境并不适用。
特别是弱网环境,在弱网环境,弱的本质是抖动,即借用带宽激进重传可能会造成拥塞加剧进而造成更多丢包,因此模型应该修改,加入抖动。
有效带宽依然不变 C ′ = C ⋅ ( 1 − k r ) C'=C\cdot(1-kr) C′=C⋅(1−kr),而一次成功传输的概率变为 1 - p*(1 + g*r),g 为一个抖动指标度量,传输到成功的次数为 1 1 − p ⋅ ( 1 + g ( t ) ⋅ r ) \dfrac{1}{1-p\cdot(1+g(t)\cdot r)} 1−p⋅(1+g(t)⋅r)1,传输时间变为 T = M C ⋅ ( 1 − k r ) ⋅ ( 1 − p ⋅ ( 1 + g ( t ) ⋅ r ) ) T=\dfrac{M}{C\cdot(1-kr)\cdot(1-p\cdot(1+g(t)\cdot r))} T=C⋅(1−kr)⋅(1−p⋅(1+g(t)⋅r))M,加入 r 后的传输效能:
E = M T = C 2 ⋅ ( 1 − k r ) 2 ⋅ ( 1 − p ⋅ ( 1 + g ( t ) ⋅ r ) ) M E=\dfrac{M}{T}=\dfrac{C^2\cdot(1-kr)^2\cdot(1-p\cdot(1+g(t)\cdot r))}{M} E=TM=MC2⋅(1−kr)2⋅(1−p⋅(1+g(t)⋅r))
g 可定义如下:
# low, high 表示丢包原因,越小越容易恢复, 差值越大抖动越大
l, h = -1, 2
def g():
return random.uniform(l, h)
整个代码如下:
l, h = -7, -3
def g():
return random.uniform(l, h)
def f(x, k, p):
g_val = g()
return (1 - k * x) * (1 - p * (1 + g_val * x))
k, p = 1, 0.9
x = np.linspace(0, 1, 100)
y = [f(i, k, p) for i in x]
plt.plot(x, y)
plt.title(f'f(x)=(1-k*x)(1-p*(1+g*x)), p = {p}, low = {l}, high = {h}')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
再一次用不同的 g 来看 E 的变化。
首先看一个轻微抖动对程序员小经理的轻微欺骗,这种情况下只要稍微激进些,注意不要太大,还是可以用带宽换恢复效率:
现在看一个强烈抖动对程序员小经理的终极欺骗,小经理检测到一个丢包便让程序员写一段激进重传的代码,然而显然这是误判,我们看一下模型的表现:
然而还有一种情况,虽然抖动很大,但并没有拥塞加剧,这可能是信号本身造成的:
这种情况下无论激进与否,长远看影响不大,但可能会加剧抖动,使系统在不稳定边缘颠簸,也不是好事。综合看上面三个图,丢包率没变,但结果却大相径庭,小经理用相同的策略应对,失败是必然的。
所谓保守和激进主要量化误判,而在弱网环境误判的代价高昂,试错成本高。在优良的环境,错误不会叠加,反可采取激进策略,一次性快速解决问题。在好网环境,丢包是一个毛刺,在当时就是 100% 丢包率,激进策略落入上述模型的 x 关于 E 的上升区间。
这其实是一个普遍方法论,穷时则紧衣缩食,富时则花天酒地,往往在困难时期,越要采取稳健谨慎的策略。
弱网,强网,环境是客观的,无法改变,适应环境就能减少无用功。仍然用万能公式 E = bw / delay 观之,弱网环境激进传输,delay 很容易膨胀,bw 却不易增加,导致无用功增加,而好的网络,bw 很容易增加,delay 却可能依然不膨胀,激进一点何乐而不为。弱网激进属于硬刚。
以下仅对 RTO 重传建模展示更一般的原理,RACK,NACK 同理(但更复杂)。
假设(这是一个简单但合理的假设)网络时延 D 服从正态分布 N ( μ D , σ D 2 ) N(\mu_D,\sigma_D^2) N(μD,σD2),误判条件则是如果数据包的实际传输时间 D 超过了 RTO,sender 会误判报文丢失并进行重传,误判的概率 q 可以表示为 q = P ( D > R T O ) = 1 − Φ ( R T O − μ D σ D ) q=P(D>RTO)=1-\Phi\left(\frac{RTO-\mu_D}{\sigma_D}\right) q=P(D>RTO)=1−Φ(σDRTO−μD) 其中 KaTeX parse error: Undefined control sequence: \Ph at position 1: \̲P̲h̲ 是标准正态分布的累积分布函数。
丢包率 p 会影响网络的整体状态,进而影响 D 的分布。p 很大时,网络恶化, μ D \mu_D μD和 σ D \sigma_D σD 都可能增加,p 与 μ D \mu_D μD 和 σ D \sigma_D σD 之间存在某种正相关的函数关系。可假设 μ D = α p + β \mu_D=\alpha p+\beta μD=αp+β, σ D = γ p + δ \sigma_D=\gamma p+\delta σD=γp+δ 其中, α \alpha α, β \beta β, γ \gamma γ, δ \delta δ 是常数,可以通过实验或历史数据拟合获得。
代入误判率 q,可以得到: KaTeX parse error: Expected group as argument to '\right' at end of input: …p+\delta}\right,简单的函数单调性分析获知,p 越大,q 越大。
则,合理的做法是,如果 p 很大,RTO 就要设置很大,但传统 tcp 的实现并未体现,所以这又是一个值得优化的点,未完待续…
浙江温州皮鞋湿,下雨进水不会胖。