最近我意识到了一件事:我实际上对UDP一无所知。好吧,我知道它是无连接的,没有三次握手过程,所以它对传输的质量不作任何保证。但是,在实际工程应用时,UDP的这些特征意味什么呢?

我启用了5个VPS(虚拟专用服务器,译者注),在7个小时相互发送UDP包,不过网络负载并不大(不过可以尝试下加大负载的情况)。每台服务器,每9-11秒就会随机地接收一个包并且发送5-10个包,包的大小从16到1016字节不等。

其中两个服务器位于新泽西州(NJ)的同一个数据中心,其余三台分别位于洛杉矶(LA)、阿姆斯特丹(NLD)和东京(JPN)。

可靠性分析

我想知道的第一件事是UDP到底有多不可靠。看到下表,我很好奇,我们是在讨论25%,50%,75%的传送率吗?

包的接收数目

 
 
- 2981/2981 2888/2889 2964/2964 3053/3054
3016/3016 - 3100/3101 2734/2735 3054/3054
2901/2941 2932/2975 - 2938/2942 2712/2712
3038/3038 2771/2772 2724/2724 - 2791/2791
2551/2552 2886/2886 2836/2838 2887/2887 -

包的接收率

 
 
- 100 99.97 100 99.97
100 - 99.97 99.97 100
98.64 98.55 - 99.86 100
100 99.97 100 - 100
99.96 100 100 100 -

这些数据远超过我的预期。我原以为从NLD—JPN一线会有明显超出均值的丢包,但是事实并不是这样的。反而是从LA发出、传送到NJ的数据有些异常。原因何在?

首先,我将原因锁定在包的大小。我会使包尽量小(16字节的头,0-1000字节的有效数据):

每种大小的包的丢失个数

0-115 116-215 216-315 316-515 516-715
13 11 12 13 23

没有什么异常。那么,这些包丢失的时间如何分布呢?

不幸的是,我没有保存时间戳啊(Why?!),但是我统计了每一对服务器间丢包时间分布。从LA到NJ2的丢失的所有的43个包中,其中29个包在第1-2分钟内丢失。NJ1的包也大部分在刚开始很短的时间内丢失。

 

排队

我关注的另一个点是排队。

为了探讨这个问题,我们首先要讨论下数组的逆序数。逆序数就是数组中位置顺序与大小顺序相反的一对数。假设现有一个数组10,8,3,7,4,那么你必须要调换8次才能达到正确的顺序,这8次分别是:((10,8),(10,3),(10,7),(10,4),(8,3),(8,7),(8,4),(7,4))。

逆序数

 
- 0 2994 2581 4658
0 - 3147 2459 4645
3980 3861 - 3237 4010
3125 1826 3133 - 4189
3920 4417 4147 4425 -

不知道你觉得怎样,我不确定这组数据是否有价值。这确实看上去很高,当然,使用UDP的一个很重要的原因是你可以丢弃掉某些包。如果你发送了10000个包,最后一个包先来,之前的9999个包之后才依次到来,那么你就不需要做9999次调换了,直接把那第1个包丢掉即可。

如果我们把比已经处理过的包的号码小的包丢弃会怎样?比如,现在有5个包来了,1,5,4,3,6,7,由于我们已经处理过了5,所以把3和4给丢弃了。那么还剩下几个“good”的包呢?

正常顺序的包的数目

 
- 100 52.40 55.94 36.77
100 - 52.47 54.22 38.02
41.72 42.32 - 50.48 39.34
46.32 59.34 44.79 - 39.27
980 1083 1141 1087 -

正常顺序的包的比率

 
- 100 52.40 55.94 36.77
100 - 52.47 54.22 38.02
41.72 42.32 - 50.48 39.34
46.32 59.34 44.79 - 39.27
38.40 37.53 40.20 37.65 -

做一个小小的调整,如果我们将5个包整合到一起,再次使用上面的丢弃算法:

正常顺序的包的数目(包整合之后):

 
- 2981 2061 2235 1807
3016 - 2214 2041 1889
1868 1873 - 2066 1720
2200 2273 1920 - 1712
60.38 62.51 61.13 59.99 -

正常顺序的包的比率(包整合之后):

 
- 100 71.34 75.40 59.17
100 - 71.40 74.63 61.85
63.52 62.96 - 70.22 63.42
72.42 82.00 70.48 - 61.34
1541 1804 1735 1732 -

 

结论:

没有长时间的、大量的数据做支撑,很难得到任何结论。然而,上面的数据表明UDP的可靠性还是相当不错的。但是距离越远,遇到的跳变就越多,这也意味着发生不可预知错误的概率就越大,但是如果一切都还OK,距离也不成问题了。

排队机制是个问题。通过整合包,我们发现性能有了很大的提升。在许多场合,排队都不会产生质的影响,除非你在疯狂发包,否则通过一个简单的时间戳和接收端的重排机制,UDP的性能依旧可观。

我会做更多的测试、更长的时间、更多的数据、更多的地点。同时,我还会把UDP和TCP的相关性能做个对比。但是无论如何,我认为,可靠性超出我预期的UDP会成为我工具箱中的一员了。