亂序的網(wǎng)絡(luò)包為什么會(huì)導(dǎo)致重傳呢?下面簡(jiǎn)單介紹一下:
在正常情況下,接收方收到包的Seq號(hào)總是順序的,比如在每個(gè)包長(zhǎng)度為1460的情況下,Seq號(hào)可能是這樣的:0,1460,2920,4380…… (每個(gè)相差1460)。接收方知道下一個(gè)包的號(hào)碼應(yīng)該是什么,比如4380之后應(yīng)該是4380+1460=5840。如果收到的不是5840,接收方就知道包序亂了,它會(huì)回復(fù)一個(gè)包給發(fā)送方,說(shuō)“我要的是5840(即Ack 5840)”。如果接下來(lái)收到的還不是5480,那接收方每收到一個(gè)包,就會(huì)發(fā)一次“我要的是5840”給發(fā)送方,直到收到5840為止(如下圖所示)。
對(duì)于發(fā)送方來(lái)說(shuō),持續(xù)收到“我要的是5840”不但意味著5840可能跑到其它包后面了,還可能意味著5840已經(jīng)丟失。RFC里這樣定義: 如果發(fā)送方收到三次以上的“我要的是X”,即可認(rèn)為包X丟失,立即啟動(dòng)快速重傳。上圖演示了這個(gè)過(guò)程??焖僦貍鞑坏匦聜鬏斄?可能)丟失的包,還會(huì)減小 TCP發(fā)送窗口,對(duì)性能的影響僅次于超時(shí)重傳。分析到這里,我仿佛看到一絲曙光。
亂序一般是由發(fā)送方或者網(wǎng)絡(luò)設(shè)備導(dǎo)致的。由于手頭只有在Windows客戶(hù)機(jī)抓的包,所以我無(wú)法進(jìn)一步確認(rèn)。便匆匆趕去機(jī)場(chǎng),飛往北京了。在飛機(jī)上擬了一個(gè)計(jì)劃:
1. Isilon和其它服務(wù)器一樣,估計(jì)有類(lèi)似Large Segment Offload的機(jī)制,也許關(guān)閉后能減少亂序。
2. 把Isilon和Windows客戶(hù)端連到同一臺(tái)空閑的Switch,盡量排除網(wǎng)絡(luò)設(shè)備導(dǎo)致的亂序。
3. 在Isilon上再抓個(gè)網(wǎng)絡(luò)包確認(rèn)。
到了北京,已經(jīng)是晚上了。和幾位來(lái)自香港,美國(guó),北京等地的現(xiàn)場(chǎng)工程師在全聚德邊吃邊聊。原來(lái)他們已經(jīng)做過(guò)很多方面的嘗試,包括我計(jì)劃中的第二點(diǎn), 但客戶(hù)要求的80MB/s的讀性能一直無(wú)法達(dá)到。客戶(hù)端也換過(guò)幾臺(tái),結(jié)果都差不多。目前看起來(lái)網(wǎng)絡(luò)設(shè)備和客戶(hù)端都沒(méi)有問(wèn)題,難道根本原因出在Isilon 上了?這和我早上在網(wǎng)絡(luò)包里看到的現(xiàn)象倒是吻合的。也許明天把Isilon的網(wǎng)絡(luò)參數(shù)調(diào)一下,問(wèn)題就解決了。到這個(gè)時(shí)候,我還是挺樂(lè)觀的。
第二天一早,便趕到了C電視臺(tái)的新大樓,比約定時(shí)間還早了2小時(shí)。更悲催的是比客戶(hù)早了3小時(shí)……第一次到現(xiàn)場(chǎng),才體會(huì)到現(xiàn)場(chǎng)工程師的苦。搭個(gè)測(cè)試 環(huán)境也花了好長(zhǎng)時(shí)間,等到真正可以測(cè)試,已經(jīng)是下午了。令人興奮的是,Isilon上果然有Large Segment Offload的設(shè)置,我滿(mǎn)懷希望的關(guān)閉了這個(gè)功能?,F(xiàn)場(chǎng)工程師立即啟動(dòng)一個(gè)新的讀測(cè)試……結(jié)果令我們大跌眼鏡,讀性能比之前還差一點(diǎn),降到了 70MB/s以下。這究竟是怎么回事?還有哪些設(shè)置可能會(huì)導(dǎo)致亂序?LACP昨天被現(xiàn)場(chǎng)工程師關(guān)掉,沒(méi)什么好查的。我一下子不知道如何是好了。對(duì)著等我下 一步建議的幾位同事,不知道該說(shuō)些什么?,F(xiàn)場(chǎng)工程師習(xí)慣性的抓了一個(gè)包,叫我過(guò)去看。這一看更是一身冷汗,果然沒(méi)有亂序的包了。我之前的猜測(cè)沒(méi)有錯(cuò),亂序 是由Large Segment Offload導(dǎo)致的。但為什么消除了亂序之后性能沒(méi)有得到改善呢?再看重傳率,還是一樣高。難道我從一開(kāi)始就走錯(cuò)胡同,重傳根本就不是亂序?qū)е碌?我不 得不一個(gè)人坐到角落里,再次打開(kāi)昨天早上研究過(guò)的網(wǎng)絡(luò)包。一個(gè)一個(gè)的查看亂序的包,果然看到了一些很有趣的現(xiàn)象。如下圖所示,雖然亂序的比例很大,但是每 個(gè)亂序都是相鄰兩個(gè)包的顛倒,這樣接收方永遠(yuǎn)不會(huì)發(fā)出三個(gè)以上的“我要的是X”,也不會(huì)觸發(fā)快速重傳。
再逐個(gè)分析重傳的網(wǎng)絡(luò)包,現(xiàn)象就更加有趣了。如下圖所示,接收方明明收到了Seq 20440(Frame No. 3),但它發(fā)送了4個(gè)“Ack 20440”給發(fā)送方,觸發(fā)了發(fā)送方的快速重傳機(jī)制。這說(shuō)明接收方的TCP層在收到20440之前,已經(jīng)收到了 21900,23360,24820,26280。這個(gè)結(jié)果表明,客戶(hù)端在把包從網(wǎng)絡(luò)層交給TCP層的時(shí)候,自己把包打亂了。為什么我們知道客戶(hù)端只是打亂20440,而不是丟棄呢?在發(fā)送方重傳的Seq 20440(Frame No. 14)到達(dá)接收方之前,接收方又發(fā)送了“Ack 28900”,這表明接收方的TCP層收到了28900之前的所有包,包括20440。從以上分析可以得出,重傳的根本原因發(fā)生在操作系統(tǒng)或者網(wǎng)卡驅(qū)動(dòng),和Switch或者Isilon完全沒(méi)有關(guān)系。
這結(jié)果是何等出人意料,以至于我自己都難以接受。不但顛覆了我前一天早上的分析結(jié)果,而且無(wú)法說(shuō)服同事和客戶(hù):我們已經(jīng)測(cè)試了7臺(tái)客戶(hù)端,結(jié)果都是 一樣的,難道7臺(tái)同時(shí)出問(wèn)題了?這概率低得難以置信。接下來(lái)的就是一場(chǎng)辯論,C電視臺(tái)派出了一位網(wǎng)絡(luò)專(zhuān)家,企圖說(shuō)服我客戶(hù)端沒(méi)有問(wèn)題。我無(wú)法解釋為什么會(huì) 碰到如此低概率的事情,他也無(wú)法反駁我在網(wǎng)絡(luò)包中看到的問(wèn)題。一直拉鋸到夜里12點(diǎn),客戶(hù)才答應(yīng)第二天提供另外7臺(tái)客戶(hù)端供我們測(cè)試,但是有一個(gè)要求,必 須給提供他們一個(gè)官方的分析報(bào)告,證明的確是客戶(hù)端導(dǎo)致的問(wèn)題。
和客戶(hù)吃完晚飯,已經(jīng)凌晨1點(diǎn)。JW萬(wàn)豪非常貼心,準(zhǔn)備好了巧克力,掀好被子,拆好拖鞋??上覜](méi)有機(jī)會(huì)享受,等寫(xiě)完報(bào)告,已經(jīng)到了凌晨3點(diǎn)半。沒(méi) 睡多久,morning call就來(lái)了……再次感嘆現(xiàn)場(chǎng)工程師真辛苦。這天我是真的信心滿(mǎn)滿(mǎn)的到C電視臺(tái)的,因?yàn)榇蠖鄶?shù)重傳的包都被我逐一研究過(guò)?,F(xiàn)場(chǎng)工程師手腳麻利,很快就測(cè) 出結(jié)果,在7臺(tái)同時(shí)讀寫(xiě)的情況下,每臺(tái)都到100MB/s以上,大大超過(guò)了客戶(hù)的期望值,甚至達(dá)到客戶(hù)機(jī)單網(wǎng)卡的理論極限了。在場(chǎng)的現(xiàn)場(chǎng)工程師們異常興 奮,給測(cè)試結(jié)果拍照,截屏,甚至拍了一段視頻。他們被這個(gè)項(xiàng)目壓抑太久了,需要好好慶祝。
而我也背起筆記本,揮手向這棟造型詭異的建筑,向這個(gè)詭異的問(wèn)題告別。匆匆趕往首都機(jī)場(chǎng),家里還有生病的老婆,斷奶的孩子,還要沒(méi)搬完的家……