閱讀446 返回首頁    go 阿裏雲 go 技術社區[雲棲]


什麼是MTU?為什麼MTU值普遍都是1500?

大學那會我玩魔獸世界,我的職業是法師,然後經常有朋友找我我帶小號,帶小號的方式是衝到血色副本裏麵把所有怪拉到一起,然後一起用AOE技能瞬間殺掉,在學校玩的時候沒什麼問題,但是放假在家的時候,我發現每次我拉好怪,放技能AOE的那個瞬間,很大概率會掉線,也不是網速問題,當時很多人也遇到同樣的問題,看到個帖子說,把自己的MTU改成1480就行了,當時也不知道啥是MTU,就改了,發現還真的可以,就愉快地打遊戲去了,多年以後我才知道MTU的重要性。

什麼是MTU

Maximum Transmission Unit,縮寫MTU,中文名是:最大傳輸單元。

這是哪一層網絡的概念?

從下麵這個表格中可以看到,在7層網絡協議中,MTU是**數據鏈路層**的概念。MTU限製的是數據鏈路層的payload,也就是**上層協議**的大小,例如IP,ICMP等。

OSI中的層 功能 TCP/IP協議族
應用層 文件傳輸,電子郵件,文件服務,虛擬終端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
表示層 數據格式化,代碼轉換,數據加密 沒有協議
會話層 解除或建立與別的接點的聯係 沒有協議
傳輸層 提供端對端的接口 TCP,UDP
網絡層 為數據包選擇路由 IP,ICMP,RIP,OSPF,BGP,IGMP
數據鏈路層 傳輸有地址的幀以及錯誤檢測功能 SLIP,CSLIP,PPP,ARP,RARP,MTU
物理層 以二進製數據形式在物理媒體上傳輸數據 ISO2110,IEEE802,IEEE802.2

MTU有什麼用?

舉一個最簡單的場景,你在家用自己的筆記本上網,用的是路由器,路由器連接電信網絡,然後訪問了www.baidu.com,從你的筆記本出發的一個以太網數據幀總共經過了以下路徑:

筆記本 -> 路由器 -> 電信機房 -> 服務器

其中,每個節點都有一個MTU值,如下:

1500     1500                 1500
筆記本 -> 路由器 -> 電信機房  -> 服務器

假設現在我把筆記本的MTU最大值設置成了1700,然後發送了一個超大的ip數據包(2000),這時候在以外網傳輸的時候會被拆成2個包,一個1700,一個300,然後加上頭信息進行傳輸。

1700     1500                1500
筆記本 -> 路由器 -> 電信機房 -> 服務器

路由器接收到了一個1700的幀,發現大於自己設置的最大值:1500,如果IP包DF標誌位為1,也就是不允許分包,那麼路由器直接就把這個包丟棄了,根本就不會到達電信機房,也就到不了服務器了,所以,到這裏我們就會發現,MTU其實就是在每一個節點的管控值,隻要是大於這個值的數據幀,要麼選擇分片,要麼直接丟棄。

為什麼是1500?

其實一個標準的以太網數據幀大小是:1518,頭信息有14字節,尾部校驗和FCS占了4字節,所以真正留給上層協議傳輸數據的大小就是:1518 - 14 - 4 = 1500,那麼,1518這個值又是從哪裏來的呢?

假設取一個更大的值

假設MTU值和IP數據包大小一致,一個IP數據包的大小是:65535,那麼加上以太網幀頭和為,一個以太網幀的大小就是:65535 + 14 + 4 = 65553,看起來似乎很完美,發送方也不需要拆包,接收方也不需要重組。

那麼假設我們現在的帶寬是:100Mbps,因為以太網幀是傳輸中的最小可識別單元,再往下就是0101所對應的光信號了,所以我們的一條帶寬同時隻能發送一個以太網幀。如果同時發送多個,那麼對端就無法重組成一個以太網幀了,在100Mbps的帶寬中(假設中間沒有損耗),我們計算一下發送這一幀需要的時間:

( 65553 * 8 ) / ( 100 * 1024 * 1024 ) ≈ 0.005(s)

在100M網絡下傳輸一幀就需要5ms,也就是說這5ms其他進程發送不了任何數據。如果是早先的電話撥號,網速隻有2M的情況下:

( 65553 * 8 ) / ( 2 * 1024 * 1024 ) ≈ 0.100(s)

100ms,這簡直是噩夢。其實這就像紅綠燈,時間要設置合理,交替通行,不然同一個方向如果一直是綠燈,那麼另一個方向就要堵成翔了。

既然大了不行,那設置小一點可以麼?

假設MTU值設置為100,那麼單個幀傳輸的時間,在2Mbps帶寬下需要:

( 100 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 ≈ 5(ms)

時間上已經能接受了,問題在於,不管MTU設置為多少,以太網頭幀尾大小是固定的,都是14 + 4,所以在MTU為100的時候,一個以太網幀的傳輸效率為:

( 100 - 14 - 4 ) / 100 = 82%

寫成公式就是:( T - 14 - 4 ) / T,當T趨於無窮大的時候,效率接近100%,也就是MTU的值越大,傳輸效率最高,但是基於上一點傳輸時間的問題,來個折中的選擇吧,既然頭加尾是18,那就湊個整來個1500,總大小就是1518,傳輸效率:

1500 / 1518 =  98.8%

100Mbps傳輸時間:

( 1518 * 8 ) / ( 100 * 1024 * 1024 ) * 1000 = 0.11(ms)

2Mbps傳輸時間:

( 1518 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 = 5.79(ms)

總體上時間都還能接受

最小值被限製在64

為什麼是64呢?

這個其實和以太網幀在半雙工下的碰撞有關,感興趣的同學可以自行去搜索。

在我玩遊戲的時候,為什麼把MTU改成1480就不卡了?

路由器默認值大多都是1500,理論上是沒有問題的,那為什麼我玩遊戲的時候改成1480才能流暢呢?原因在於當時我使用的是ADSL上網的方式,ADSL使用的PPPoE協議。

PPPoE

PPPoE協議介於以太網和IP之間,協議分為兩部分,PPP( Point to Point Protocol )和oE( over Ethernet ),也就是以太網上的PPP協議,而PPPoE協議頭信息為:

| VER(4bit) | TYPE(4bit) | CODE(8bit) | SESSION-ID(16bit) | LENGTH(16bit) |

這裏總共是48位,也就是6個字節,那麼另外2個字節是什麼呢?答案是PPP協議的ID號,占用兩個字節,所以在PPPoE環境下,最佳MTU值應該是:1500 - 4 - 2 = 1492。

我的上網方式

當時我的上網路徑如下:

PC -> 路由器 -> 電信

我在路由器進行撥號,然後PC連接路由器進行上網。

最根本原因

問題就出在路由器撥號,如果是PC撥號,那麼PC會進行PPPoE的封裝,會按照MTU:1492來進行以太網幀的封裝,即使通過路由器,路由器這時候也隻是轉發而已,不會進行拆包。

而當用路由器撥號時,PC並不知道路由器的通信方式,會以網卡的設置,默認1500的MTU來進行以太網幀的封裝,到達路由器時,由於路由器需要進行PPPoE協議的封裝,加上8字節的頭信息,這樣一來,就必須進行拆包,路由器把這一幀的內容拆成兩幀發送,一幀是1492,一幀是8,然後分別加上PPPoE的頭進行發送。

平時玩遊戲不卡,是因為數據量路由器還處理得過來,而當進行群怪AOE的時候,由於短時間數據量過大,路由器處理不過來,就會發生丟包卡頓的情況,也就掉線了。

帖子裏麵提到的1480,猜測可能是盡量設小一點,避免二次撥號帶來的又一次PPPoE的封裝,因為時間久遠,沒辦法回到當時的場景再去抓包了。

結論

1518這個值是考慮到傳輸效率以及傳輸時間而折中選擇的一個值,並且由於目前網絡鏈路中的節點太多,其中某個節點的MTU值如果和別的節點不一樣,就很容易帶來拆包重組的問題,甚至會導致無法發送。

最後更新:2017-10-10 10:33:19

  上一篇:go  RDC如何構建一個基於Composer的PHP項目
  下一篇:go 浙江:實施“鳳凰行動”;雲棲大會:馬雲將發布重磅消息