从流量控制算法谈网络优化-TCP核心原理理解
hi,大家好,又是新的一周,周末在朋友圈讀到一篇網絡優化的文章,感覺文章比較接地氣,有實驗測試,有數據分析,想分享給大家,讓我們再次加強對TCP以及網絡優化的理解。
作者簡介
費良宏,AWS Principal Developer Advocate。在過去的20多年一直從事軟件架構、程序開發以及技術推廣等領域的工作。他經常在各類技術會議上發表演講進行分享,他還是多個技術社區的熱心參與者。他擅長Web領域應用、移動應用以及機器學習等的開發,也從事過多個大型軟件項目的設計、開發與項目管理。目前他專注與云計算以及互聯網等技術領域,致力于幫助中國的 開發者構建基于云計算的新一代的互聯網應用。可以通過這個郵箱與我聯系lianghon@amazon.com。
文章最初發表在:
https://aws.amazon.com/cn/blogs/china/talking-about-network-optimization-from-the-flow-control-algorithm/
授權后,發表在公眾號:極客重生
前言
誕生于1974年的TCP協議(Transmission Control Protocol,傳輸控制協議)絕對算得上是最古老的網絡協議之一,很可能是當今互聯網上使用最多的網絡協議。我們每個人每天不經意間就會發送和接收幾十萬甚至超過一百萬以上的TCP數據包用來收看視頻、玩游戲或者進行網絡社交。
再進一步,也許你還了解目前互聯網上最流行的兩種傳輸協議UDP和TCP。UDP概括起來是一個“發送后不管”的協議。它是無狀態的,沒有擁塞控制或可靠的傳輸支持,這也導致了網絡運營商會針對UDP協議的限流。我們經常看到UDP被用于DNS(域名系統)和NTP(網絡時間協議)等。與之相對,TCP則像是UDP互補的孿生兄弟,提供了可靠的傳輸和流量控制,因此TCP協議也變得相當復雜。
人們通常認為TCP和UDP的主要區別就是TCP給我們提供了可靠的數據包傳輸。當然這是TCP最重要的功能之一,但TCP協議還為我們提供了流量控制。流量控制關乎網絡使用的公平性,這對互聯網的有效運行是至關重要的。TCP使用多種擁塞控制策略來避免擁塞。具體來講,TCP會為每條連接維護一個“擁塞窗口”來限制可能在端對端間傳輸的未確認分組的總數量。并且,TCP在一個連接初始化或超時后使用一種“慢啟動”機制來增加擁塞窗口的大小。所謂的“慢啟動”,指的是初始值雖然比較低,但其增長極快:當每個分段得到確認時,擁塞窗口會增加一個MSS(Maximum segment size),使得在每次往返時間(Round-trip time,RTT)內擁塞窗口能高效地雙倍增長。設想一下,如果沒有這種形式的流量控制,互聯網注定會在海量的數據傳輸之下不堪使用。
許多年來,不同的流量控制算法已經在各種TCP堆棧中實現和使用。你可能聽說過TCP上的一些術語,例如Cubic、Tahoe、Vegas、Reno、Westwood,以及最近流行的BBR等。這些都是TCP中使用的不同擁塞控制算法。這些算法的作用是決定發送方應該以多快的速度發送數據,并同時適應網絡的變化。如果沒有這些算法,我們的互聯網一定會被數據填滿并且崩潰。
在Linux 下檢查當前可用的擁塞算法可以使用如下命令:
sysctl net.ipv4.tcp_available_congestion_control
在我的這臺機器上就得到了如下的結果 :
net.ipv4.tcp_available_congestion_control = reno cubic bbr bbr2 hybla highspeed htcp veno westwood vegas
如果想了解當前使用了哪一種擁塞算法可以使用以下命令:
sysctl net.ipv4.tcp_congestion_control
得到的結果如下。可以看出當前使用的是Cubic算法
net.ipv4.tcp_congestion_control = cubic
這里提到的Cubic 是一種較為溫和的擁塞算法,它使用三次函數作為其擁塞窗口的算法,并且使用函數拐點作為擁塞窗口的設置值。Linux內核在2.6.19后使用該算法作為默認TCP擁塞算法。我們今天所使用的絕大多數Linux 分發版本,例如Ubuntu、Amazon Linux 等均將Cubic作為缺省的 TCP流量控制的擁塞算法。
?
BBR 算法
TCP的BBR(Bottleneck Bandwidth and Round-trip propagation time,BBR)是谷歌在2016年開發的一種新型的TCP 擁塞控制算法。在此以前,互聯網主要使用基于丟包的擁塞控制策略,只依靠丟失數據包的跡象作為減緩發送速率的信號。這樣做的的效果還是不錯的,但隨著全球化互聯網的迅速普及,我們所使用的網絡已經發生了巨大的變化。我們擁有了越來越大的帶寬,而現在的互聯網質量也越來越好。于是我們觀察到了一些新的問題,比如影響延遲的緩沖區膨脹的問題。BBR嘗試通過使用全新的擁塞控制來解決這個問題,它使用基于延遲而不是丟包作為決定發送速率的主要因素。下圖是一個原理的演示:
https://cloud.google.com/blog/products/gcp/tcp-bbr-congestion-control-comes-to-gcp-your-internet-just-got-faster
?
為什么BBR會更好?
盡管我省略了很多細節,但還免不了是涉及相對復雜的概念。但需要了解的是,使用BBR,可以獲得顯著的網絡吞吐量的提升和延遲的降低。吞吐量的改善在遠距離路徑上尤為明顯,比如跨太平洋的文件或者大數據的傳輸,尤其是在有輕微丟包的網絡條件下。延遲的改善主要體現在最后一公里的路徑上,而這一路徑經常受到緩沖膨脹(Bufferbloat)的影響。所謂“緩沖膨脹”指的網絡設備或者系統不必要地設計了過大的緩沖區。當網絡鏈路擁塞時,就會發生緩沖膨脹,從而導致數據包在這些超大緩沖區中長時間排隊。在先進先出隊列系統中,過大的緩沖區會導致更長的隊列和更高的延遲,并且不會提高網絡吞吐量。由于BBR并不會試圖填滿緩沖區,所以在避免緩沖區膨脹方面往往會有更好的表現。
?
看一看BBR的表現
BBR從4.9版本開始就已經出現在Linux內核之中,可以通過一個簡單的sysctl命令來啟用。在我的測試中,我使用兩臺EC2 實例作為測試的硬件,安裝的操作系統為Ubuntu 20.04。為了滿足測試的要求,我將Linux 核心替換為我定制的5.8版本的核心。這兩臺實例運行在同一個區域的同一個可用區之下。實例的類型是c5.2xlarge,網卡為Amazon ENA,實例的網絡最大帶寬為10Gbps。
第一個測試是簡單的帶寬測試,看看我們可以從兩臺實例之間的單個TCP流量中得到什么。使用iperf3的測試顯示了兩臺實例之間的帶寬為4.98 Gbits/秒。這足以運行我們的實驗。
延遲對TCP吞吐量的影響
在現實的使用中,我所用到的服務器可能分布在世界的各個地區,所以我主要關心的是服務器之間的網絡性能,當然網絡間的延遲是在所難免的。在這個測試中,我們將使用Linux流量控制工具(tc) 在兩臺實例之間引入100ms的往返時間。這大致相當于從美國俄勒岡的us-west-2 訪問位于日本東京的github.com服務器(52.192.72.89)之間的延遲。
現在我們來看一下正常情況下兩臺實例的網絡延遲
接下來,可以像下面這樣在兩臺服務器的收發每個方向增加50ms的延遲。
sudo tc qdisc replace dev eth0 root netem latency 50ms
(注:取消上述的設置可以使用這個命令?sudo tc qdisc del dev eth0 root?)
如果我們用ping命令做一個檢測,現在可以看到100ms的往返時間
好了,該輪到我們的第一個測試了,我先用Cubic擁塞算法開始,因為這是目前最常用的TCP擁塞控制算法。
sudo sysctl -w net.ipv4.tcp_congestion_control=cubic
iperf3的測試顯示平均傳輸速度為611 Mbits/秒。這是延遲對TCP吞吐量影響的第一條線索。與我們的初始測試(4.98Gbits/秒)相比,唯一發生變化的是引入了100ms的往返延遲。現在我們將擁塞控制算法設置為bbr,再進行一次測試。
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
結果與上一次很相似,約為 609 Mbits/秒,這比使用Cubic的結果略低。到目前為止,我們還沒有看到真正的變化。
?
丟包對吞吐量的影響
我們要重復上面同樣的測試,但要增加少量的丟包。通過下面的命令,我只在服務器(發送方)端引入1.5%的丟包量。
sudo tc qdisc replace dev eth0 root netem loss 1.5% latency 50ms
在使用Cubic算法的第一次測試中,顯示出吞吐量的急劇下降;吞吐量下降到了10.5 Mbs/秒。這個下降的幅度大約是99.7%,導致這個鏈路的帶寬基本上無法滿足數據傳輸的需要了。
如果我們用BBR重復完全相同的測試,我們會看到比Cubic有顯著的改善。使用BBR后,吞吐量下降到333Mbits/秒,下降了45%。
上面的測試顯示了丟包和延遲對TCP吞吐量的巨大影響。在一個高延遲的路徑上,僅僅是少量的數據包丟失(1.5%)就會產生了巨大的影響。在這些較長的路徑上使用除BBR以外的任何其他技術,當出現哪怕是少量的丟包時,都會造成很大的問題。也只有BBR在任何超過1.5%的丟包損失時都能保持一個不錯的吞吐量數字。
Andree Toonk 在他的博客中驗證了了使用不同擁塞控制算法、延遲和丟包參數所做的各種TCP吞吐量測試的全套測試,證明了在一定的丟包率(1.5%、3%)的情況下BBR的出色表現。結果如下圖:
網絡吞吐量 – 各種擁塞控制算法的測試結果
注意:一個TCP會話使用的擁塞控制算法只與局部有關。所以,兩個TCP系統可以在TCP會話的兩邊使用不同的擁塞控制算法。換句話說:服務器(發送方),可以在本地啟用BBR,而客戶端不需要知道BBR,也不需要啟用BBR。
?
TCP ss (socket statistics) 工具
當我們在探索調整TCP性能的時候,一定不要忘記使用socket statistics,也就是ss命令。例如下圖所示,ss這個工具可以顯示大量的套接字信息,包括使用的TCP流控算法,每個TCP會話的往返時間以及計算出的帶寬和兩個對等體之間的實際傳輸速率等,可以很好的用于網絡監測和優化。
?
何時使用BBR
網絡在沒有丟包的情況下,Cubic和BBR對于這些較長時延的鏈路都有很好的表現。而在中度丟包的情況下,BBR的表現就非常突出了。為什么這一點很重要呢?或者換一個說法,為什么要針對丟包情況而進行優化?對于這個問題,讓我們考慮一下這樣的場景:我們在不同的地方放置有服務器,需要在系統或者服務器之間有源源不斷的數據傳輸。例如日志文件、數據庫同步、業務數據的異地備份等等。而在復雜的網絡環境下,會因為各種原因而出現丟包的情況。在這種場景下,BBR將會大放異彩,幫助您維護更好的網絡數據傳輸。
顯而易見,BBR對所謂的“長肥網絡”(帶寬延遲積大、丟包率高的網絡)非常有效,在CDN和視頻應用等場景下也被證明有很好的表現。事實上,Youtube、Spotify和Dropbox大規模應用BBR已經有了很多的積累。這主要是因為BBR會積極地提升到最佳發送速率,使你的視頻流加載或者文件下載速度更快。這是Dropbox 在2017年的一篇技術博客,非常值得我們學習。
Optimizing web servers for high throughput and low latency
?
BBR的缺點
看這個標題很覺得奇怪吧。明明只要執行一個sysctl命令,你就能獲得更好的吞吐量,網絡用戶就會獲得更好的體驗,有什么理由不這樣做呢?好吧,BBR自出世以來已經收到了一些批評,首先,因為它傾向于搶占Cubic算法的帶寬,在網絡公平性上明顯存在不足;其次BBR的機制會導致高重傳率;第三點是在Wi-Fi環境下用戶的網速明顯變慢。綜合來看,BBR與Cubic 相比只能說互有優劣,各有其擅長的領域。
BBRv2 點展望
針對BBR 的問題,BBRv2的目標就是解決第一版中存在的一些主要缺點,其改進包括了還使用聚合/運行中的參數增強了網絡建模,并增加了對ECN(顯式擁塞通知)的支持等。為便于理解,我們可以通過這樣一張表來了解這幾個擁塞算法的異同。
注:ECN是指網絡瓶頸通知發送方在用盡緩沖區并開始“丟尾”數據包之前放慢速度的一種方式
現在我們了解了BBRv2,我們再將之前的實驗重復一次,看一看BBRv2的具體表現。
我們先將擁塞算法設定為BBRv2
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr2
接下來,使用iperf3 進行測速,結果如下:
對比BBRv2、BBRv1的這兩個實驗,我們能明顯的觀察到BBRv2 較之BBR速度明顯變“慢”了。但這可以說是一件好事,因為這或許是BBRv2廣泛應用的前提。
隨著BBRv2的出現,Dropbox 已經在其Dropbox Edge Network上進行了試用。在這篇博客中深入討論了BBRv2的實踐,值得一讀。
Evaluating BBRv2 on the Dropbox Edge Network
這篇文章的結論對于BBRv2有很高的評價,特摘錄出來:
"在我們的測試中,BBRv2顯示了以下特性:
對于網速較低的用戶來說,帶寬可以與CUBIC媲美。
對于網速較高的用戶來說,帶寬可以與BBRv1媲美。
丟包率比BBRv1低4倍;但仍然比CUBIC高2倍。
傳輸中的數據比BBRv1低3倍;但略低于CUBIC。
RTTs較BBRv1低;但仍然比CUBIC高。
與BBRv1相比,RTT具有更高的公平性。
總的來說,BBRv2在BBRv1基礎上有了很大的改進,而且在需要更高帶寬的情況下,它更接近于成為Reno/CUBIC的完全替代品。添加實驗性的ECN支持,我們甚至可以看到他可以成為Datacenter TCP (DCTCP)的完全替代者."
BBR具體實現分析:來自Google的TCP BBR擁塞控制算法深度解析
最后
自2019年算法被提出, BBR2 已有了3個年頭,但仍處于Alpha/Preview Release。各大主流的Linux 分發版本中并沒有集成進來。有意了解這個項目不妨通過GitHub 的這個地址來關注一下:
https://github.com/google/bbr
但是如果想嘗鮮卻有點麻煩,只能通過編譯Linux Kernel 來得到tcp_bbr.ko 這個內核模塊。另一種選擇是不妨體驗一下我剛剛完成的一個基于Ubuntu 20.04 的Linux kernel,其中就包括了這個BBRv2。
- END -
看完一鍵三連在看,轉發,點贊
是對文章最大的贊賞,極客重生感謝你
推薦閱讀
圖解Linux 內核TCP/IP 協議棧實現|Linux網絡硬核系列
TCP/IP協議精華指南pdf發布
來自Google的TCP BBR擁塞控制算法深度解析
總結
以上是生活随笔為你收集整理的从流量控制算法谈网络优化-TCP核心原理理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TCP/IP协议精华指南pdf发布
- 下一篇: 深入理解数据结构和算法