[轉(zhuǎn)]再說TCP神奇的40ms

轉(zhuǎn)自 http://m.blog.csdn.net/article/details?id=52980399

TCP是一個復雜的協(xié)議雁社,每個機制在帶來優(yōu)勢的同時也會引入其他的問題。 Nagel算法和delay ack機制是減少發(fā)送端和接收端包量的兩個機制, 可以有效減少網(wǎng)絡包量项郊,避免擁塞膛檀。但是锰镀,在特定場景下, Nagel算法要求網(wǎng)絡中只有一個未確認的包咖刃, 而delay ack機制需要等待更多的數(shù)據(jù)包泳炉, 再發(fā)送ACK回包, 導致發(fā)送和接收端等待對方發(fā)送數(shù)據(jù)嚎杨, 造成死鎖花鹅, 只有當delay ack超時后才能解開死鎖,進而導致應用側(cè)對外的延時高枫浙。 其他文字已經(jīng)介紹了相關(guān)的機制刨肃, 已經(jīng)有一些文章介紹這種時延的場景古拴。本文結(jié)合具體的tcpdump包,分析觸發(fā)delay ack的場景真友,相關(guān)的內(nèi)核參數(shù)黄痪, 以及規(guī)避的方案。
背景
給redis加了一個proxy層盔然, 壓測的時候發(fā)現(xiàn)桅打, 對寫入命令,數(shù)據(jù)長度大于2k后愈案, 性能下降非常明顯挺尾, 只有直連redis-server的1/10. 而get請求影響并不是那么明顯。
分析
觀察系統(tǒng)的負載和網(wǎng)絡包量情況站绪, 都比較低潦嘶, 網(wǎng)絡包量也比較小, proxy內(nèi)部的耗時也比較短崇众。 無賴只能祭出tcpdump神奇掂僵, 果然有妖邪。
22號tcp請求包顷歌, 42ms后服務端才返回了ack锰蓬。 初步懷疑是網(wǎng)絡層的延時導致了耗時增加。Google和km上找資料眯漩, 大概的解釋是這樣: 由于客戶端打開了Nagel算法芹扭, 服務端未關(guān)閉延遲ack, 會導致延遲ack超時后赦抖,再發(fā)送ack舱卡,引起超時。
原理
Nagel算法队萤,轉(zhuǎn)自維基百科

if there is new data to send

  if the window size >= MSS and available data is >= MSS

    send complete MSS segment now

  else

    if there is unconfirmed data still in the pipe

      enqueue data in the buffer until an acknowledge is received

    else

      send data immediately

    end if

  end if

end if

簡單講轮锥, Nagel算法的規(guī)則是:
如果發(fā)送內(nèi)容大于1個MSS, 立即發(fā)送要尔;
如果之前沒有包未被確認舍杜, 立即發(fā)送;
如果之前有包未被確認赵辕, 緩存發(fā)送內(nèi)容既绩;
如果收到ack, 立即發(fā)送緩存的內(nèi)容还惠。

延遲ACK的源碼如下:net/ipv4/tcp_input.c

Paste_Image.png

基本原理是:
如果收到的數(shù)據(jù)內(nèi)容大于一個MSS饲握, 發(fā)送ACK;
如果收到了接收窗口以外的數(shù)據(jù), 發(fā)送ACK救欧;
如果處于quick mode歪今, 發(fā)送ACK;
如果收到亂序的數(shù)據(jù)颜矿, 發(fā)送ACK寄猩;
其他, 延遲發(fā)送ACK
其他都比較明確骑疆, quick mode是怎么判斷的呢田篇? 繼續(xù)往下看代碼:

Paste_Image.png

影響quick mode的一個因素是 ping pong的狀態(tài)。 Pingpong是一個狀態(tài)值箍铭, 用來標識當前tcp交互的狀態(tài)泊柬, 以預測是否是W-R-W-R-W-R這種交互式的通訊模式, 如果處于诈火, 可以用延遲ack兽赁, 利用Read的回包, 將Write的回包冷守, 捎帶給發(fā)送方刀崖。


如上圖所示, 默認pingpong = 0拍摇, 表示非交互式的亮钦, 服務端收到數(shù)據(jù)后, 立即返回ACK充活, 當服務端有數(shù)據(jù)響應時蜂莉,服務端將pingpong = 1, 以后的交互中混卵, 服務端不會立即返回ack映穗,而是等待有數(shù)據(jù)或者ACK超時后響應。
問題
按照前面的的原理分析幕随,應該每次都有ACK延遲的蚁滋,為什么我們測試小于2K的數(shù)據(jù)時, 性能并沒有受到影響呢合陵?
繼續(xù)分析tcpdump包:

Paste_Image.png

按照Nagel算法和延遲ACK機制枢赔, 上面的交互如下圖所示, 由于每次發(fā)生的數(shù)據(jù)都包含了完整的請求拥知, 服務端處理完成后, 向客戶端返回命令響應時碎赢, 將請求的ACK捎帶給客戶端低剔,節(jié)約一次網(wǎng)絡包。

Paste_Image.png

再分析2K的場景:


如下表所示, 第22個包發(fā)送的數(shù)據(jù)小于MSS襟齿, 同時姻锁,pingpong = 1, 被認為是交互模式猜欺, 期待通過捎帶ACK的方式來減少網(wǎng)絡的包量位隶。 但是, 服務端收到的數(shù)據(jù)开皿,并不是一個完整的包涧黄,不能產(chǎn)生一次應答。服務端只能在等待40ms超時后赋荆,發(fā)送ACK響應包笋妥。
同時,從客戶端來看窄潭,如果在發(fā)送一個包春宣, 也可以打破已收數(shù)據(jù) > MSS的限制。 但是嫉你,客戶端受Nagel算法的限制月帝, 一次只能有一個包未被確認,其他的數(shù)據(jù)只能被緩存起來幽污, 等待發(fā)送嫁赏。


觸發(fā)場景
一次tcp請求的數(shù)據(jù), 不能在服務端產(chǎn)生一次響應油挥,或者小于一個MSS
規(guī)避方案
只有同時客戶端打開Nagel算法潦蝇, 服務端打開tcp_delay_ack才會導致前面的死鎖狀態(tài)。 解決方案可以從TCP的兩端來入手深寥。

服務端:
關(guān)閉tcp_delay_ack, 這樣攘乒, 每個tcp請求包都會有一個ack及時響應, 不會出現(xiàn)延遲的情況惋鹅。 操作方式:
echo 1 > /proc/sys/net/ipv4/tcp_no_delay_ack
但是则酝, 每個tcp請求都返回一個ack包, 導致網(wǎng)絡包量的增加闰集,關(guān)閉tcp延遲確認后沽讹, 網(wǎng)絡包量大概增加了80%,在高峰期影響還是比較明顯武鲁。

設(shè)置TCP_QUICKACK屬性爽雄。 但是需要每次recv后再設(shè)置一次。 對應我們的場景不太適合沐鼠,需要修改服務端redis源碼挚瘟。
客戶端:
關(guān)閉nagel算法叹谁,即設(shè)置socket tcp_no_delay屬性。

staticvoid_set_tcp_nodelay(intfd) {
intenable =1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,(void*)&enable,sizeof(enable));
}

避免多次寫乘盖, 再讀取的場景焰檩, 合并成一個大包的寫;避免一次請求分成多個包發(fā)送订框, 最開始發(fā)送的包小于一個MSS析苫,對我們的場景, 把第22號包的1424個字節(jié)緩存起來穿扳, 大于一個MSS的時候衩侥,再發(fā)送出去, 服務端立即返回響應纵揍, 客戶端繼續(xù)發(fā)送后續(xù)的數(shù)據(jù)顿乒, 完成交互,避免時延泽谨。
參考資料:
http://jerrypeng.me/2013/08/mythical-40ms-delay-and-tcp-nodelay/
http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201231214038740/
http://blog.chinaunix.net/uid-28387257-id-3658980.html
https://github.com/torvalds/linux/blob/master/net/ipv4/tcp_input.c

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末璧榄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子吧雹,更是在濱河造成了極大的恐慌骨杂,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雄卷,死亡現(xiàn)場離奇詭異搓蚪,居然都是意外死亡,警方通過查閱死者的電腦和手機丁鹉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門妒潭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人揣钦,你說我怎么就攤上這事雳灾。” “怎么了冯凹?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵谎亩,是天一觀的道長。 經(jīng)常有香客問我宇姚,道長匈庭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任浑劳,我火速辦了婚禮阱持,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呀洲。我一直安慰自己紊选,他們只是感情好啼止,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布道逗。 她就那樣靜靜地躺著兵罢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滓窍。 梳的紋絲不亂的頭發(fā)上卖词,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機與錄音吏夯,去河邊找鬼此蜈。 笑死,一個胖子當著我的面吹牛噪生,可吹牛的內(nèi)容都是我干的裆赵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼跺嗽,長吁一口氣:“原來是場噩夢啊……” “哼战授!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起桨嫁,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤植兰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后璃吧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楣导,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年畜挨,在試婚紗的時候發(fā)現(xiàn)自己被綠了筒繁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡巴元,死狀恐怖毡咏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情务冕,我是刑警寧澤血当,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站禀忆,受9級特大地震影響臊旭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜箩退,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一离熏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧戴涝,春花似錦滋戳、人聲如沸钻蔑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咪笑。三九已至,卻和暖如春娄涩,著一層夾襖步出監(jiān)牢的瞬間窗怒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工蓄拣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扬虚,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓球恤,卻偏偏與公主長得像辜昵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子咽斧,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容

  • 個人認為堪置,Goodboy1881先生的TCP /IP 協(xié)議詳解學習博客系列博客是一部非常精彩的學習筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,060評論 0 8
  • 1.這篇文章不是本人原創(chuàng)的收厨,只是個人為了對這部分知識做一個整理和系統(tǒng)的輸出而編輯成的晋柱,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,077評論 6 174
  • 轉(zhuǎn)載:http://blog.csdn.net/sctq8888/article/details/7398967案...
    礪豪閱讀 3,693評論 1 5
  • 套接字選項SO_RESUEADDR 即使端口處于2MSL狀態(tài),使用該選項诵叁,仍然能夠在該端口建立連接雁竞。服務器常會設(shè)置...
    Myth52125閱讀 1,411評論 0 0
  • 18.1 引言 TCP是一個面向連接的協(xié)議。無論哪一方向另一方發(fā)送數(shù)據(jù)之前拧额,都必須先在雙方之間建立一條連接碑诉。本章將...
    張芳濤閱讀 3,390評論 0 13