正文
很多人會認為一個好的TCP擁塞控制算法會讓連接配接加速,這種觀點是錯誤的,恰恰相反,所有的擁塞控制算法都是為了TCP可以在貪婪的時候懸崖勒馬,大多數時候,擁塞控制是降低了資料發送的速度。
我在本文中會針對近期跟業内朋友之間的聊天記錄,總結出三言兩語。
TCP擁塞控制的終極目标絕對不是加快資料發送的速度,這種了解非常自私且膚淺!它的終結目标是在公平占有帶寬的前提下無限度提高帶寬的使用率!
如果你隻關注一個獨立的TCP連接配接本身,那麼你也許永遠都不可能設計出什麼比較好的算法,但如果你不從一個獨立的連接配接入手,貌似更加虛無飄渺,畢竟你能拿到且駕馭的隻有一個連接配接!
考慮一個程序排程器的設計,從2.6.23開始,大家普遍認為Linux排程器迎來了一個新的階段,即CFS階段,相比之下,O(1)排程器僅僅像是一個過渡,而之前的O(n)排程器就略顯初級了。當時我也關注了這個新排程器好一陣子,正如我這段時間關注TCP BBR一樣...So,我們來看一下CFS到底好在哪裡,以至于它可以占據Linux預設排程器這頭把交椅。
首先我們反問,CFS讓程序運作的速度更快了嗎?非也,有點經驗的都知道,對于追求高吞吐的環境,CFS反而讓程序運作的速度更慢了。比較膚淺的認知角度,一般很容易将“好”和“快”緊密聯系在一起,但事實上,站在更高的層次,你看到的将不再是一個獨立的程序,而是一整機器裡面所有的程序!CFS到底好在哪裡?
從其名字上就可以看出,其好處在于“完全公平”!它治療了O(1)排程器中幾乎所有的不公平排程導緻的症狀,比如IO消耗型與互動程序之間的搶占與饑餓問題,比如排程粒度問題,等等所有這些問題,引入一個虛拟時鐘後,公平性得到了非常精确的度量,這些問題最終得到了解決。從開始到最後,沒有任何獨立的程序“被加快了運作速度”!
最終,CFS讓所有程序在公平持有CPU時間的前提下,讓CPU盡可能滿負荷運轉,即提高了CPU的使用率。整個過程沒有毛刺,非常平滑。
----------------------------------------------------
間中,我們來看看平滑代替毛刺的好處,眼睛隻要直視就是那麼的帥!《 德國佬又火了!奧迪終于把球形輪胎造了出來…》!
----------------------------------------------------
現在回到TCP本身,BBR和當年的CFS一樣,引起了衆人的關注。我想我已經引出了“如何設計一個好的TCP擁塞控制算法”的思路了。
站在全球網際網路上空往下看,你看到的是所有的TCP連接配接,而不僅僅是你的機器上建立的那一個或者那幾個。這就是格局不同,你的偏見自然也就消除了。上海自然要和北京競争,但北京不這麼看,不管哪裡好了,都是它北京的,不是嗎?如何讓所有的TCP連接配接公平共享全部的網際網路帶寬,是TCP擁塞控制算法的根本!注意兩個關鍵點,其一,公平地共享,其二,盡可能全部的帶寬。
這個問題是一個世界難題,沒有程序排程器那麼簡單!
程序排程器是作用于一個CPU的,或者簡單點說,作用于一台機器。這台機器就在你的手上,你,也就是排程器的設計者完全可以看清楚目前機器裡發生的一切,一切不公平症狀,一切浪費現象可以讓設計者盡收眼底,你可以強制性拿一個程序的資源給予另一個程序,你也可以殺死過于貪婪的程序...對于TCP而言,根本沒有一個可以站在全球網際網路往下看的高人,TCP擁塞控制是完全分布式的,每一個設計者都隻能看到自己機器上的那一部分連接配接!
然而,TCP擁塞控制之是以如此難并不是什麼所謂分布式導緻的,其實分布式一點也不難,難點在于TCP擁塞控制總是被誤解,是以說在設計算法的時候,稍不留神就會南轅北轍,本來是避免擁塞的,實際上是添堵的。
為什麼會被誤解?其實凱撒早就說過,人們總是看到自己希望看到的。這句話還有另一層意思,人們樂于把自己看到的局部當成所有。人們可以一眼看到一整機器的程序,是以設計出一個好的程序排程器是很容易的,是以CFS出現了。但是大家看不到所有的TCP連接配接,大家看到的隻是自己的TCP連接配接,是以大家隻能臆測,我好,你也好。至于算法是否添堵,可能完全不是出于惡意,而完全是目光的短淺和格局之不高導緻的。
一個正确的,且好的TCP擁塞控制算法應該是顧及所有的連接配接的,如果TCP不夠快,那就應該讓所有TCP都提速,這點展現了帶寬使用率的提高;如果TCP已經足夠快,那任何連接配接都不能更快,這點展現了公平性。換成人話非常簡單,如果你覺得開車走省道慢,那就上高速,如果你已經在高速公路上,請不要變道超車。
多麼簡單的道理,可還是能看到道路上變道超車的,我可能表達有問題,是所有的司機都在玩變道超車,如果讓這些人來設計TCP擁塞控制算法,會好到哪裡去呢?不幸的是,世界上TCP單邊加速玩的最火的那批人,和這批中國好司機是同一批人,無論什麼資源,唯一的目标除了搶,還是搶。
其實,我并非一個道德說教者,說什麼人人為我,我為人人的算法才是一個好的算法,說的就好像我自己做到了似的...
我是被兩位大師罵了才知錯就改了,其實我也走火入魔過...
前一段時間吧,我修改了一個擁塞算法,呈給一位大師評解,姑且叫大師1吧,值得"炫耀"的就是我這個算法非常快,甚至比BBR還要快,但是被惡損了一頓,我的算法“競賽肯定第一”,但是卻“不負責任”...這種是毀人品的算法。後來,我試着讓兩個或者多個運作同一個算法的流一起傳輸資料,果然...一些流會瞬間把剩餘的流帶寬壓榨到0!連敵友都不分了,簡直就是流氓算法啊!這個算法從此也就閱後即焚了,完全不可用。
...
如果這還不算,那麼另一位大師2則徹底讓我覺得自己根本就狗屁都不懂。
這位大師在國外,跟我有時差,且能讀中文但不寫中文,我與之相反,我是能讀英文但寫起來費勁,是以隻能郵件交流。主題還是擁塞控制,我由于急功近利隻是問了“怎麼讓TCP資料發送速度更快”這樣的問題,答案很簡單,忽略擁塞控制并補償性重傳即可,然後我就寫了一個“忽略擁塞控制的擁塞控制算法”,并且挑釁般的作為回應。然後的郵件裡就出現了fxxk詞彙,還有suck...說我根本就不懂基本的原則,并力勸我辭去工作回家仔細學習和思考。我都快哭了。
...........
大師2的教導在大師1之前,但是大師1給了我具體怎麼做的方向和方法,我除了發自内心的感謝之外,能做的就是寫一些“抨擊TCP擁塞控制算法”的文章來把人人為我,我為人人的基督教理念傳遞給更多的人。出于對兩位大師以及各路朋友的尊重,我不會貼出與之相關的代碼,郵件原文以及聊天記錄,消化加工後的理念,由我這裡直接始發。
BBR
本文的最後,我通過BBR算法稍微聊一下什麼樣的算法是正确的算法。
BBR和當年的CFS一樣,這個我已經說過了。但是BBR目前仍處在比較初級的階段,起初呢,我認為它的問題在于:
1.收斂太慢,即不會即時降速降窗,而是要在幾個RTT内完成;
2.向上探測太遲。難道問題1是對這個的補償也說不準;
3.大BDP緩存下的搶占性有待商榷;
4.BBR依托的SDN基礎設施...
...
可以看到,這種最初的領悟展現了我個人多麼深厚的技術功底。然而後來,經大師指點,我才發現,原來BBR的最大問題在于,它引入的新擁塞控制架構很容易被誤用,具體的請參見 http://blog.csdn.net/dog250/article/details/54754784
如果幾個三流的比我還差的人使用新架構寫算法,那麼網際網路崩潰指日可待,幸運的是,即便崩潰,也隻是國内的網際網路崩潰,在這個領域,國外的月亮就是圓的,畢竟人家比我們受教育程度更深,懂得博弈理論,即便從自私者的角度來看,損人不利己的事情也是做不來的。值得注意的是,有知識不代表有文化,我一直覺得國内的大學其實就是技校,特别是華中科技大學,幾乎是定向給華為,BAT等巨頭培養進階技工的。
回到BBR。對于BBR帶來的新架構,最嚴重的是,之前有人拼速度拼重傳的時候,會有prr降窗,這點是不受算法子產品控制的,現在好了,直接寫個回調,完全繞開了降窗,大家都去添堵去了TCP設計的原則層面,RFC裡貌似也把公平性提到了至高的地位。因為如果不把公平性作為基本原則,那麼整個環将不是閉合的,帶寬資源早晚會用盡,此時盲目的AI非MD過程将會促使大家都想往前搶,最後誰也過不去,如此一來,網際網路将完全不可用!基于這點,所有搞“TCP單邊加速”的個人和廠商都是在做鑽空子的壞事,其出發點就是錯誤的。當然,這類廠商的出發點往往不是TCP層面的,而是業務層面的,這倒是無可厚非,畢竟不是一個領域,我也無權過問太多,TCP對于它們而言隻是工具,真到哪天網際網路崩潰了,他們還是會用卡車運硬碟的方式來進行資料傳輸的,到時候,高速公路上堵的水洩不通的運硬碟的卡車與TCP一樣,也隻是個工具,而已。
----------------------
怎麼樣的做法是正确的呢?
先來介紹一個君子算法,即LEDBAT算法,可以看看 http://www.rfc-base.org/txt/rfc-6817.txt,其wiki是 https://zh.wikipedia.org/wiki/LEDBAT
它的思想在搞“加速”的那幫人看來,其實有點搞笑,它的存在是為了填補CUBIC之流不Bloat Buffer時候的空隙的,一旦有其它流量造成了排隊,LEDBAT馬上騰地方退讓。這種算法是應該被“加速者”第一時間抛棄的算法,但是它在iOS和Win10裡卻大行其道,LEDBAT主要用于軟體更新,這種事一般可以在背景默默進行,優先級比較低,是以發明一個背景靜默的君子式LEDBAT算法,實則是在提高帶寬使用率上無所不用其極啊,然而這個算法又不會跟其它的流量争搶帶寬,絲毫不會應該高優先級流量的公平性,難道不是很帥的算法嗎?LEDBAT在表達的是,你們去前面堵着去吧,我沒你們重要,我慢慢走就行。。。
BBR不是君子式算法,它是要參與公平競争的,我不主動欺負人,但是被人欺負,我不會怕事的,是以BBR在LEDBAT上增加了Probe More的過程,同時,與LEDBAT退讓不同,BBR将其改成了輕柔緩和的Drain Less。
所有這些都不是最近剛剛出現的,在此之前,Vegas算法則代表了一種正确的做法,它最終沒有上位是因為Vegas部署有個前提,那就是同一時間全部部署成Vegas,然而這是不可能的,隻要有Reno或者CUBIC在,Vegas的“正确做法”就會吃虧。現實就是這樣,劣币驅良币,CUBIC明明是錯誤的算法,但因為它可以使用率很低但很簡單的方法快速收斂到可用帶寬,是以就一直是大家認可的算法,所有人都在默默忍受着Bufferbloat,而這個問題帶來的額外排隊延遲會大大降低互動式TCP連接配接的互動體驗,同時嚴重影響實時性的協定,比如NTP之類。
CUBIC是一定會堵路的,Buffer被堵了之後,互動應用的資料就會被排隊,時延增加,互動性自然下降。
我一直好奇的問題是,為什麼Reno,CUBIC之流在經過慢啟動之後的AI增窗過程叫做擁塞避免,相反,這種盲目的一路走到黑的增窗方式一定會導緻擁塞的,即擁塞不可避免。這個過程是玷污了“擁塞避免”這個詞呢,還是說僅僅是一個定義呢?下面的一篇文章給出答案,現在的時間是周六早上7點半,該睡一會兒了。
寫在最後的序:
“昨夜入城市,歸來淚滿襟”的那是傻逼,自己不養蠶便是了,幹嘛嫉妒别人穿絲綢。
今天又是周末,又可以半夜起來折騰,本文寫作開始于五點半,完成于早七點二十,在此之前,我花了一個小時時間讀了《盧比孔河》之25頁,再之前的一個小時,我看了一些關于道路規劃的東西,主要在令人不安的電腦上...現在,本來我想睡一覺,然而睡不着,就想去登高望遠,隻可惜旁邊的山都太矮小了...自從甘孜歸來,深圳的山就成小土堆了...實際一點,去買菜,做飯才是解決之道,做什麼飯呢?哈哈,重慶帶來的老火鍋!
----我希望你能看到這篇文章。