深度思考|TCP协议存在那些缺陷?
作者:dog250
https://www.zhihu.com/question/47560918/answer/2302296292
TCP如何優化吞吐率,我很直接說優化不了,這讓我甩開了很多令人尷尬的麻煩事兒。但我可以聊一聊。
為什么優化不了?因為滑動窗口。
當我這么說時,有人不由分說就懟,說“如果是cwnd limited”呢?我要表達的是,cwnd limited原因有二,如果你的cc算準了,那就是網絡原本就是擁塞的,如果你的cc沒算準,那是你的cc的問題,換句話說,cwnd決定的是你TCP連接吞吐的下限,卻不限制其上限。為什么因為滑動窗口?因為滑動窗口本質上是一個“停-等”策略。
“停-等”怎么了?因為要等,所以要停,一停就慢了(也叫HoL阻塞)。
隊頭阻塞(英語:Head-of-line blocking,縮寫:HOL?blocking)在計算機網絡的范疇中是一種性能受限的現象。它的原因是一列的第一個數據包(隊頭)受阻而導致整列數據包受阻。例如它有可能在緩存式輸入的交換機中出現,有可能因為傳輸順序錯亂而出現,亦有可能在HTTP流水線中有多個請求的情況下出現。
等什么?等buffer被填滿。
什么buffer?就是接收窗口。
等接收窗口被填滿有什么問題嗎?問題就在這里!
那么要取消滑動窗口嗎?這個最后再談。先說本質問題。
問題在于,這塊作為滑動窗口的buffer有一個約束,要求其中的字節序列號必須連續。這意味著這個buffer便不再是一塊無差別隨機訪問的內存了,而變成了一個隊列。一旦出現一個hole,傳輸過程就必須停下來等待它被填充,期間窗口的滑動是被阻滯。
當我這么說時,有人不由分說就懟,說“流量控制是對所有有連接協議的基本要求,滑動窗口就是為了流控存在的”。我表達的意思是,首先,當出現hole并在它被補齊前,TCP擁塞狀態機完全接管cwnd的計算,cc將不起作用,此時要么你的連接成為rwnd limited,要么帶寬估計失真,誆論高吞吐,其次,滑動窗口并非流量控制的唯一方式。誕生于1970~1980年代的TCP從來就不是為性能而生的。當人們意識到性能問題的時候,隨即就出現了依賴out-of-order queue的selective ACK。但于本質問題無補,基因決定了上限。
設計傳輸協議,肯定要把端到端語義和傳輸語義分開,不然還要什么分層模型。簡單說,傳輸只關注數據包看不見序列號,端到端只重排字節看不見數據包。這需要在字節流的序列號空間和數據包之間做一次映射。
問題在于,致使TCP沒有作出這種設計的根源是什么?
在于它的“流式設計”。下面的鏈接可以找到故事的一部分:
Transmission Control Protocol (TCP) 1973-1976
分歧在于拆包和組裝,為了讓分組交換站在電路交換的對面,重新組裝由端到端負責,這就不強求TCP流經過相同路由器了,但這個策略未竟全功。
未竟全功,核心原因是TCP協議被設計的時候并沒有承載TCP數據的“數據報協議分組”,這是一個先有雞先有蛋的問題,在1973年~1976年,IP尚未從TCP中分離出來,所以IP無法承載TCP,更別提UDP了。UDP是當IP從TCP中分離出來后,作為IP協議的等價語義在TCP層的補充而被后來添加的。
那么TCP只能自己承載自己,直接在分組交換網傳輸。
允許亂序是分組交換的基本特征之一,TCP協議也因此將保序邏輯放在了端到端,然而對于傳輸邏輯,TCP依然更像一條虛電路流,而不像數據報分組。
這是TCP后續停-等buffer,GBN低效的根源。為什么呢?
整個傳輸邏輯的實體不是TCP數據包,而是沒有邊界的TCP字節流。換句話說,發送端一次發送1000字節的數據,到了接收端,可能收到2個數據包,一個20字節,另一個980字節,也可能收到1000個數據包,每一個1字節,當然,更大可能是依然是一個1000字節的數據包。無論如何,接收端無法“基于數據包做ACK,只能對字節做ACK”,但主機處理處理依然以數據包為單位。這逆轉了人們設計協議時對時間和空間做trade-off時的偏好。
對空間的關注超過了對吞吐的關注。為每一個字節安排一個ACK,將使TCP協議頭變得冗長到不可接受,這不僅不能帶來吞吐的提升,還會消耗大量的帶寬用于ACK本身的管理開銷。
摒棄數據包的概念,直接對TCP的字節流對積累ACK可以解決上述問題。積累ACK自然而然就等價于滑動窗口和GBN了。
整個故事是,流式抽象導致了必須基于字節進行ACK,進而積累確認和GBN重傳被認為是性價比最高的。這是一個很低效的設計,但管用。
selective ACK是一種向正確方式的回歸,但依然沒能擺脫“基于字節ACK”的夢魘,SACK看上去很別扭并勉強,因為它不得不委曲于TCP Option中,空間受限而不能求全,本質原因還是最初的那個,如果給SACK安排了不受限制的空間,ACK報文將變得冗長。
我簡單畫了一個TCP本應該在分組交換網中的正確姿勢:
非常清晰的兩層結構。接收窗口限制了可用buffer的大小,而buffer只有夠不夠的問題,如果空間不足,顯式發送抑制消息給ACK邏輯即可,ACK將抑制消息反饋到源端。
與buffer的解釋類似,網絡傳輸只有帶寬滿不滿,擁塞與否的問題,而這些完全通過congestion control,pacing邏輯等完成,令牌桶里完全序列號的概念。
端到端語義和傳輸語義分離的好處不勝枚舉:
很容易統計重傳率指標,需要傳輸的字節在端到端子層,實際傳輸的字節在傳輸子層。
網絡傳輸可以肆意并行,無需關注亂序,重組等問題,以最大化帶寬利用率為目標。
確認數據包而不是確認字節,靈活實現積累ACK或selective ACK,ACK報文可壓縮,可編碼。
...
簡單展示一個ACK報文的樣子:
現在看在新的設計下,滑動窗口本身的問題。要不要取消它?滑動窗口要取消,問題在于,首先,如何做流量控制,其次,流量控制如何使用buffer。
第一個問題很容易:
buffer是標量而非矢量,只看大小不看方向,只要尚未超過最大使用限額,就可以收數據。
設置可用buffer最大值以及最大允許的突發,超過限額即發送源抑制。
看第二個問題。如果buffer中數據有hole不連續,應用程序如何收走數據?如果數據一直不被收走,buffer總會沒有空閑空間。這不是又回到問題的原點了嗎?問題的解決在于使用buffer的方式。
不同于標準TCP一個連接獨占buffer的方式:
新的設計采用子連接復用的方式讓多個連接共享同一個buffer:
buffer粒度更細,施展空間更大,同一子連接HoL阻塞概率更低。
QUIC大概就是這個意思吧。
...
我不認同NAK的原因還是因為它會引入紛亂的誤判。
...
現在,可以把上面的設計部署在IDC網絡(互聯網數據中心(Internet Data Center), 簡稱IDC)使用流體滲透原理去對抗incast,也可以部署在MPTCP邏輯通道上。
MultiPath TCP(MPTCP)由互聯網工程任務組(IETF)MultiPath TCP工作組研發,其目的是允許傳輸控制協議Transmission Control Protocol(TCP)連接使用多個路徑來最大化信道資源使用。
摩爾定律?在40年中持續改變甚至逆轉人們的關注點,30年前,顯卡,網卡被稱為CPU的外設,如今CPU成了GPU,SmartNIC的外設。同理,TCP剛出來的時候,內存昂貴,帶寬昂貴,于是人們擠壓空間而不在乎時間,GBN順勢而為,TCP頭也就成了那個樣子,現在看來各種不夠,大并發場景經常遭遇bind占CPU高的問題根源就是端口號只有16bits,TLV不是更好嗎?可是那個時代不允許啊。直到空間不再昂貴,人們開始壓縮時間,吞吐性能問題就擺在眼前,可是TCP已經是那個樣子了,它就是為空間優化而生的,還能怎么辦?我總說TCP是一個過時的老協議,言外之意就是說要用新的傳輸協議了,比如QUIC,或者比QUIC更好的協議。TCP優化?到頭了。追求陸地速度就去坐高鐵,而不是坐高性能綠皮車。想了想,就寫了這篇。時間有限,先這么多...- END -
看完一鍵三連在看,轉發,點贊
是對文章最大的贊賞,極客重生感謝你
推薦閱讀
實戰|QUIC協議助力騰訊業務提速30%
實戰|QUIC協議在螞蟻集團落地
2022新年重磅技術分享|深入理解Linux操作系統
你好,這里是極客重生,我是阿榮,大家都叫我榮哥,從華為->外企->到互聯網大廠,職場經驗豐富,目前是大廠資深工程師,多次獲得公司五星員工,技術扎實,專業后端開發和后臺架構設計,熱愛底層技術,豐富的實戰經驗,分享技術的本質原理,希望幫助更多人蛻變重生,拿BAT大廠offer,培養高級工程師能力,成為技術專家,實現高薪夢想,期待你的關注!點擊藍字查看我的成長之路。
校招/社招/簡歷/面試技巧/大廠技術棧分析/后端開發進階/優秀開源項目/直播分享/技術視野/實戰高手等,?極客星球希望成為最有技術價值星球,盡最大努力為星球的同學提供技術和成長幫助!詳情查看->極客星球
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 求點贊,在看,分享三連
總結
以上是生活随笔為你收集整理的深度思考|TCP协议存在那些缺陷?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何从0搭建公司的后端技术栈
- 下一篇: 手把手教你拦截Linux系统调用