關於TCP擁塞控制的一點想法

今天又想到去年在華爲iaccess系統上遇到的問題,由於連續丟且沒有dup ack引起的TCP擁塞控制的性能問題,這個問題當時給的調參數的方案雖然緩解了問題,但不能從根本上解決此類問題,今天中午休息的時候靜下心來好好想了想,把不成熟的思路整理一下,備忘。

先拋出問題,抓包發現這個用戶對應的TCP連接上經常有突發的瞬時大流量數據,抓包看到VPN已經把包發出,到公網鏈路後出出現了大量丟包,VPN客戶端的抓包顯示這些包沒有到達客戶端。因爲沒有dup ack, VPN協議棧的擁塞控制狀態機沒有觸發快速重傳和快速恢復。按照newreno的算法,每隔一段時間, 重傳一個包,串行地把所有的重傳包都發出去,這個時間非常長,嚴重的時候幾十秒級別!從用戶的抓包看到,這種問題週期性的出現,卡得幾乎不可用。其實從抓包看到,超時重傳的第一個包,在100多毫秒以後已經收到ack了,第二個重傳包幾毫秒就收到ack,這個TCP連接已經基本恢復正常了。但是newreno的擁塞狀態機還在慢騰騰地隔一段時間發一個重傳包。好在寫公司這個協議棧的牛人留了一個可調參數,在這個case下,收到第一個重傳包的ack就把TCP擁塞狀態機切到快速重傳-快速恢復狀態。當時用了這個參數,客戶體驗提升並認可了這個方案。但是這畢竟不是一個完美的方案,我們的協議棧裏TCP擁塞控制這塊還有很大提升空間。

這個問題的源頭是因爲瞬時大流量導致了連續丟包且沒有一個ack。解決newreno擁塞控制導致的不必要延遲,是被動的方式,第一個丟包的超時導致的延遲用戶體驗就很差。 VPN作爲一箇中間設備如果能把瞬時大流量整型,像大壩泄洪一樣把流量溫和地發出去就不會導致鏈路上如此嚴重的懲罰。

後來接觸了cubic,bbr等擁塞算法,cubic和reno/newreno都是基於丟包觸發的被動的方法,沒有整型的功能。目前沒有深入學習bbr,從一些介紹上看到它的目標是讓inflight packet收斂於BDP(監測到的最大帶寬*最小延遲), 並且用pacing rate來進行流量控制。但我猜測這種突發的瞬時大流量對於bbr這種基於統計值來進行決策的算法是不友好的,等到bbr檢測到的時候可能已經晚了,丟包已經出現了。

對於這種case,我覺得基於丟包觸發的擁塞控制算法可能更有優勢,它讓我想到了基於強化學習的試錯思想,但是錯了不能白錯,要亡羊補牢,要記住教訓,需要擁塞控制算法在丟包後有一個記憶功能,並能測量到這個瞬時流量的大小。以後如果再遇到這樣的流量就進行流量整型。擁塞控制和流量整型結合起來效果纔好。把基於丟包的算法和基於流量統計、整型的算法優點結合起來,對我遇到到這個case效果會更好。流量整型就要用到buffer,用不好的話就會產生bufferbloat, 先想到這裏,有點混亂,先記下下來,有時間再繼續。。。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章