最近在做UGC项目,使用UDP协议上传,自己做了一层比较简单的拥塞控制,机制如下:
1、每个会话都有一个发送队列,根据当前计算出的发送速率匀速发送
2、服务器每秒返回一个控制消息,包含的信息有服务器接收数据包的速率和丢包率等
3、客户端根据服务器返回的控制消息调整发送队列里的数据包的发送速率
今天有一台机器突然出现只有一两KB的上传速度,这明显有问题,正常应该是占满上行带宽的。而且超时重传的数据包反而比满带宽上传时多N倍。这就怪了!按道理,发送速度如此的慢,超时应该更少才对。
后来认真分析了下,找到原因了,为了避免忘记,记录一下:
为什么只有几K的上传?
因为发送队列的发送速率是按服务器丢包率来调整的,调整代码如下:
if(lost < 5.0f)
{
send_speed *= (110.0f - lost) * (110.0f - lost) / 10000.0f;
}
else
{
send_speed *= (110.0f - lost ) / 100.0f;
}
其中send_speed是浮点型
从中可以看出,当丢包率小于5%时,是1.1到1.2倍的增长,但当丢包率大于5%,特别是特别大时,发送速率会急剧下滑,真是缓涨大落呀
那么最终可能会导致send_speed为1的结果。
从代码来看,就算是缓涨大落,速度也应该能马上调上去才对,但为什么就是调不上去呢??
呵呵,其实服务器返回的丢包率也不是真正的丢包率,而是在1秒内服务器没有收到的数据包,那么就包括了真正丢的数据包和正在路上的数据包。
现在1秒才发1到2个包,那在路上的数据包的几率就大大增加了。比如一秒才发2个包,那有一个还有路上,这丢包率就是50%了,速度怎么能上得去?
还有,发送队列里的发送速率是DWORD的,float转成DOWRD,1点几的值全白涨了,都是1
至于为什么代码会这样写,我只能说事件就是这样了,至于你信不信,反正我是信了!
为什么发送速度慢了,超时反而多了?
因为两点之间的RTT其实很小的,而我的超时值为4倍的RTT。而队列里能push16个包,发一个包就push一个包。好了,现在每秒只能发两个包了,而超时又是从放入队列时算起,这样一来在队列里呆的时间都大于4RTT了
后话:
这样挫的代码,我也无奈,老大要我四天写完,而能力有限的我加班加点用了近两周才写完,难免会出这样那样的错误。老大脸色不好,我也累。。。