最近我意識到了一件事:我實際上對UDP一無所知。好吧,我知道它是無連線的,沒有三次握手過程,所以它對傳輸的質量不作任何保證。但是,在實際工程應用時,UDP的這些特徵意味什麼呢?
我啟用了5個VPS(虛擬專用伺服器,譯者注),在7個小時相互傳送UDP包,不過網路負載並不大(不過可以嘗試下加大負載的情況)。每臺伺服器,每9-11秒就會隨機地接收一個包並且傳送5-10個包,包的大小從16到1016位元組不等。
其中兩個伺服器位於新澤西州(NJ)的同一個資料中心,其餘三臺分別位於洛杉磯(LA)、阿姆斯特丹(NLD)和東京(JPN)。
可靠性分析
我想知道的第一件事是UDP到底有多不可靠。看到下表,我很好奇,我們是在討論25%,50%,75%的傳送率嗎?
包的接收數目
接收方 |
|||||
NJ 1 |
NJ 2 |
LA |
NLD |
JPN |
|
NJ 1 |
– | 2981/2981 | 2888/2889 | 2964/2964 | 3053/3054 |
NJ 2 |
3016/3016 | – | 3100/3101 | 2734/2735 | 3054/3054 |
LA |
2901/2941 | 2932/2975 | – | 2938/2942 | 2712/2712 |
NLD |
3038/3038 | 2771/2772 | 2724/2724 | – | 2791/2791 |
JPN |
2551/2552 | 2886/2886 | 2836/2838 | 2887/2887 | – |
包的接收率
接收方 |
|||||
NJ 1 |
NJ 2 |
LA |
NLD |
JPN |
|
NJ 1 |
– | 100 | 99.97 | 100 | 99.97 |
NJ 2 |
100 | – | 99.97 | 99.97 | 100 |
LA |
98.64 | 98.55 | – | 99.86 | 100 |
NLD |
100 | 99.97 | 100 | – | 100 |
JPN |
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))。
逆序數
NJ 1 |
NJ 2 |
LA |
NLD |
JPN |
|
NJ 1 |
– | 0 | 2994 | 2581 | 4658 |
NJ 2 |
0 | – | 3147 | 2459 | 4645 |
LA |
3980 | 3861 | – | 3237 | 4010 |
NLD |
3125 | 1826 | 3133 | – | 4189 |
JPN |
3920 | 4417 | 4147 | 4425 | – |
不知道你覺得怎樣,我不確定這組資料是否有價值。這確實看上去很高,當然,使用UDP的一個很重要的原因是你可以丟棄掉某些包。如果你傳送了10000個包,最後一個包先來,之前的9999個包之後才依次到來,那麼你就不需要做9999次調換了,直接把那第1個包丟掉即可。
如果我們把比已經處理過的包的號碼小的包丟棄會怎樣?比如,現在有5個包來了,1,5,4,3,6,7,由於我們已經處理過了5,所以把3和4給丟棄了。那麼還剩下幾個“good”的包呢?
正常順序的包的數目
NJ 1 |
NJ 2 |
LA |
NLD |
JPN |
|
NJ 1 |
– | 100 | 52.40 | 55.94 | 36.77 |
NJ 2 |
100 | – | 52.47 | 54.22 | 38.02 |
LA |
41.72 | 42.32 | – | 50.48 | 39.34 |
NLD |
46.32 | 59.34 | 44.79 | – | 39.27 |
JPN |
980 | 1083 | 1141 | 1087 | – |
正常順序的包的比率
NJ 1 |
NJ 2 |
LA |
NLD |
JPN |
|
NJ 1 |
– | 100 | 52.40 | 55.94 | 36.77 |
NJ 2 |
100 | – | 52.47 | 54.22 | 38.02 |
LA |
41.72 | 42.32 | – | 50.48 | 39.34 |
NLD |
46.32 | 59.34 | 44.79 | – | 39.27 |
JPN |
38.40 | 37.53 | 40.20 | 37.65 | – |
做一個小小的調整,如果我們將5個包整合到一起,再次使用上面的丟棄演算法:
正常順序的包的數目(包整合之後):
NJ 1 |
NJ 2 |
LA |
NLD |
JPN |
|
NJ 1 |
– | 2981 | 2061 | 2235 | 1807 |
NJ 2 |
3016 | – | 2214 | 2041 | 1889 |
LA |
1868 | 1873 | – | 2066 | 1720 |
NLD |
2200 | 2273 | 1920 | – | 1712 |
JPN |
60.38 | 62.51 | 61.13 | 59.99 | – |
正常順序的包的比率(包整合之後):
NJ 1 |
NJ 2 |
LA |
NLD |
JPN |
|
NJ 1 |
– | 100 | 71.34 | 75.40 | 59.17 |
NJ 2 |
100 | – | 71.40 | 74.63 | 61.85 |
LA |
63.52 | 62.96 | – | 70.22 | 63.42 |
NLD |
72.42 | 82.00 | 70.48 | – | 61.34 |
JPN |
1541 | 1804 | 1735 | 1732 | – |
結論:
沒有長時間的、大量的資料做支撐,很難得到任何結論。然而,上面的資料表明UDP的可靠性還是相當不錯的。但是距離越遠,遇到的跳變就越多,這也意味著發生不可預知錯誤的概率就越大,但是如果一切都還OK,距離也不成問題了。
排隊機制是個問題。通過整合包,我們發現效能有了很大的提升。在許多場合,排隊都不會產生質的影響,除非你在瘋狂發包,否則通過一個簡單的時間戳和接收端的重排機制,UDP的效能依舊可觀。
我會做更多的測試、更長的時間、更多的資料、更多的地點。同時,我還會把UDP和TCP的相關效能做個對比。但是無論如何,我認為,可靠性超出我預期的UDP會成為我工具箱中的一員了。