《CDN 之我見》系列三:詳解篇(網絡優化)
時間: 2018-07-04來源:OSCHINA
前景提要
摘要: 本文作者:白金,《CDN 之我見》是一個系列文章,共由三個篇章組成,分為“原理篇”、“詳解篇”和“隕坑篇”。本篇章屬于“詳解篇”的第一部分:網絡優化。詳解篇適合那些接觸過 CDN,對 CDN 多少有些了解,但很多知識點知其然而不知其所以然,想深入了解學習的同學。
本文作者:白金
上篇回顧:《CDN 之我見》系列二:原理篇(緩存、安全) https://yq.aliyun.com/articles/599253
《CDN 之我見》是一個系列文章,共由三個篇章組成,分為“原理篇”、“詳解篇”和“隕坑篇”。本篇章屬于“詳解篇”的第一部分:網絡優化。詳解篇適合那些接觸過 CDN,對 CDN 多少有些了解,但很多知識點知其然而不知其所以然,想深入了解學習的同學。

眾所周知,當前是互聯網時代,無論大大小小的公司,無論是互聯網企業還是傳統企業,統統離不開一個“網”字,而相比之下,硬件服務器、操作系統、應用組件等,在沒有特殊必要需求的話(如果硬件不壞、軟件或系統無急需修復的 BUG、無急需實現的客戶需求),這些都是不用去主動改變。

相比之下網絡則不同,最頻繁變化的,最不想變化而又最無奈被動跟隨變化的,就是網絡質量,而 CDN 的縮寫也是 Content Delivery Network,因此在詳解篇我會把重點放在網絡上。其它的部分相對都好把控,但網絡問題存在一定的隨機性和不可預測性。如果我們可以駕馭網絡,相信在這個互聯互通的互聯網時代,我們將變得如虎添翼、叱咤風云!
為此,這里提出我對 CDN 的另一個解讀:CDN - Can Do sth. on Network(我們可以在網絡層面搞些事情)
提到優化,其實從 OSI 七層模型來講(準確說是 TCP/IP 模型,二者是不同的,具體可以 google 一下),從物理層到應用層其實都是可以優化的,優化手段各異。
L1 物理層:硬件優化(升級硬件設備,承載更多業務)
L2 鏈路層:資源好壞(尋找更快的網絡節點、確保 Lastmile 盡量短)
L3 路由層:路徑優化(尋找 A 到 B 的最短路徑)
L4 傳輸層:協議棧優化(TCP Optimization)
L7 應用層:能做的事情太多了(主要面向 HTTP 面向業務)

針對 CDN 而言,常用的是 L4 和 L7 的優化,例如上圖所述。 分布式就近部署:確保網民訪問到的 Cache Server 離他是最近的。 策略性緩存:針對明確已知的圖片、CSS、JS 等,若源站更新并不快,但卻沒有明確高值緩存多長時間,CDN Cache Server 可以自定義一個緩存時間(例如 60s),這樣可以確保在 60s 之內的同樣請求會快速給出數據而不用穿越整個 Internet 從源站獲取。 傳輸路徑優化:尋找從邊緣 CDN Cache Server 經 upper CDN Cache Server 到源站的最優傳輸路徑,確保動態傳輸的數據可以走端到端的最優路徑。 連接加速:通過修改協議棧的 Handshake Timer 來實現快速重試,以彌補由于丟包導致的重試超時。 傳輸層優化:這里主要是指 TCP 協議,針對 TCP 協議可以做很多優化策略,由于篇幅問題后面再講。 內容預?。航馕?WEB 內容,對于里面的 Object,在網民請求之前,優先由 CDN Cache Server 主動獲取并緩存下來,以縮短數據交互時間,提升網民體驗感。 合并回源:當有多個人先后下載同一個還未緩存住的內容時(例如一個 mp4 視頻文件),CDN Cache Server 做到合并連接從 upstream 拿數據,而不是幾個請求,幾個 to uptream connection,既做到了帶寬成本優化,又做到了給 upstream 降載,后請求的人還能享受之前 CDN Cache Server 已經下載過的部分文件,這部分內容直接 HIT,只有當追上第一個 downloader 的時候才一起等待 MISS 數據。 持久連接池:在 Middlemile 之間預先建立好 TCP Connection,并一直保持不斷開,當網民有新請求過來時,邊緣 CDN Cache Server 直接借助與 upper 建立好連接,直接發送 HTTP 的 GET/POST 報文到 upper CDN Cache Server,進行 TCP “去握手化”,減少由于 TCP 連接建立而造成的時間損耗(多適用于高并發小文件請求)。 主動壓縮:很多源站由于規劃設計問題或擔心負載過高問題,頁面中的 HTML、CSS、JS 文件(這種文件具有高度可壓縮性)并未壓縮傳輸,此時 CDN Cache Server 可以主動對其進行壓縮后傳輸并緩存,以減少傳輸量、降低交互時間、提升用戶體驗感。 Offline:當源站掛了怎么辦?網民訪問時,會拿不到數據。那么 CDN 此時可以策略性發送最新緩存的一份舊數據給網民,而不是生硬的告知用戶不可訪問,以提升用戶體驗感。
總之,優化策略非常多,下面將抽取其中最具通用性的網絡部分進行詳細闡述。

如前文所述,所謂路徑優化就是找到兩點間的最優路徑。
對于網絡而言,A 到 B 最快 ≠ A 距離 B 最近,從廣東聯通訪問福建聯通,可能不如廣東聯通經北京聯通再到福建聯通更快,因此要對節點做實時探測,計算最優路徑。
計算最優路徑時,還要考慮帶寬飽和度、成本、客戶敏感度問題綜合計算,因此不是看上去那么簡單的。
帶寬飽和度:作為中轉節點(例如上例所說的北京),如果帶寬本身已經沒有多少剩余,那么穿越北京的路徑優化可能會作為壓死大象的最后一根稻草,使原本還 OK 的北京節點變得不堪重負。
成本:還以北京為例,北京資源的帶寬成本肯定遠高于其它省市,例如比河北聯通、天津聯通可能要貴很多,但可能只比河北天津慢幾個毫秒(運動員起跑時最快的反應時間是 150 毫秒),那么為了這幾毫秒要多支付很多帶寬費用顯然是不值當的,那么利用北京進行中轉顯然就是不值得的(當然,有的時候就是為了和對手 PK,那也沒辦法)。
客戶敏感度:有了中轉路徑,提速效果當然是好的,但如前文所述也是有代價的,那么是所有業務流量都走最優路徑呢?還是只讓個別業務走最優路徑呢?這個就要看客戶敏感度了。例如重點大客戶,例如對質量要求較高的高價優質客戶,這些客戶可能就是首選。

如前文所述,所謂傳輸層優化主要是指 TCP 優化,這是所有互聯網行業的通用技術,是重中之重的領域,TCP 優化如果做的好,可彌補節點質量低下而造成的響應時間過大的損失。
賽馬比賽時,有好馬當然跑的快。如果馬一般(不是太差),騎手的騎術精湛,或許同樣也可以得第一,就是這個道理!
另外一點 TCP 優化重要的原因在于,TCP 是互聯網尤其是 CDN 的基礎協議,基本上所有業務都是 over TCP 來進行傳輸的,如果將 TCP 優化做好,受益面非常廣,可以說全局收益(不僅是提升客戶體驗感,也能提升內部支撐系統的使用體驗感,例如日志傳輸、配置下發等)。
談到 TCP 優化,需要先將 TCP 協議基礎知識。需要首先明確一些名詞屬于的概念。 CWND:Congestion Window,擁塞窗口,負責控制單位時間內,數據發送端的報文發送量。TCP 協議規定,一個 RTT(Round-Trip Time,往返時延,大家常說的 ping 值)時間內,數據發送端只能發送 CWND 個數據包(注意不是字節數)。TCP 協議利用 CWND/RTT 來控制速度。 SS:Slow Start,慢啟動階段。TCP 剛開始傳輸的時候,速度是慢慢漲起來的,除非遇到丟包,否則速度會一直指數性增長(標準 TCP 協議的擁塞控制算法,例如 cubic 就是如此。很多其它擁塞控制算法或其它廠商可能修改過慢啟動增長特性,未必符合指數特性)。 CA:Congestion Avoid,擁塞避免階段。當 TCP 數據發送方感知到有丟包后,會降低 CWND,此時速度會下降,CWND 再次增長時,不再像 SS 那樣指數增,而是線性增(同理,標準 TCP 協議的擁塞控制算法,例如 cubic 是這樣,很多其它擁塞控制算法或其它廠商可能修改過慢啟動增長特性,未必符合這個特性)。 ssthresh:Slow Start Threshold,慢啟動閾值。當數據發送方感知到丟包時,會記錄此時的 CWND,并計算合理的 ssthresh 值(ssthresh <= 丟包時的 CWND),當 CWND 重新由小至大增長,直到 sshtresh 時,不再 SS 而是 CA。但因為數據確認超時(數據發送端始終收不到對端的接收確認報文),發送端會驟降 CWND 到最初始的狀態。
了解了 TCP 的一些名詞屬于,其實大致也就了解了 TCP 的運作機制,但是有幾點要注意。
1.不同的操作系統、內核版本,initcwnd(初始 CWND)不同
以 Linux 為例,kernel-2.6.18 的 initcwnd 是 2,而 kernel-2.6.32 變成了 10,通過 iproute 軟件包中的 ip 命令可以修改 Linux 的 CWND 和 RWND。
具體可以參考一篇 Google 寫的 Paper,是他們提出了原始 initcwnd = 2 太小了,需要擴大的理念。

原文請參考:
https://developers.google.com/speed/protocols/tcp_initcwnd_techreport.pdf
2.單位時間內(一個 RTT)發送量不是 CWND,而是 min(CWND, RWND)
除了數據發送端有個 CWND 以外,數據接收端還有個 RWND(Receive Window,接收窗口),決定還能接收多少數據,并通過接收確認報文顯性告知數據發送端,發送端要參考 CWND 和 RWND 信息決定最終發送的數據量(packet 個數)。管道中究竟能放多少數據,取決于 CWND 和 RWND。
另一個問題:TCP 怎么了?TCP 有什么問題嗎?
如果能問出這個問題,證明同學們的關注點是正確的。
TCP 是在上個世紀六七十年代設計的,當時面向的是短距離傳輸、窄帶(可能還是半雙工通信)的鏈路環境。鏈路本身不太可能丟包,丟包基本都是因為鏈路擁塞造成的。根據早起的 TCP 擁塞控制算法,丟包 -> 降速,再丟 -> 再降,算法本身的目的是希望通過降速來規避擁塞,進而規避丟包情況。
這個算法本身的理念是正確的,但是隨著時代的發展,有了 4G,有了 WiFi,有了長距傳輸,有了策略性丟包邏輯,導致 TCP 傳輸過程中,丟包不一定就是擁塞造成的,如果按照傳統的“丟包就降速”策略來考慮問題,可能不但不能緩解問題,甚至可能會導致問題更加惡化。
舉個例子來說,在一個平均隨機丟包 50% 的鏈路上(平均發出去的包,每 2 個就必然丟 1 個),在這種環境下,發現丟包了,降速發送有用嗎?答案毋庸置疑,降速只會讓對端收到的有效數據更少。這種環境如何優化呢?很簡單,每個包發 2 遍不就可以了?這樣對端就會 100% 收到數據了,但代價就是發送端的出口流量是之前的 2 倍。
當然,真正在做 TCP 優化時不是這么簡單的,要考慮很多細節,例如如何區分丟包原因,例如該如何控制 CWND,例如如何更早的發現接收端沒收到數據,例如當對端無響應時如何快速感知等等等等…… TCP 優化實際上是在用帶寬換用戶體驗感,低成本低質量網絡雖然可以通過 TCP 優化提升體驗感,但綜合成本甚至可能比直接采購優質高價節點更高,效果還未必比優質節點直接服務好。 TCP 之所以叫優化不叫加速,是因為它可以讓那些原本應當傳輸很快,由于算法不合理導致的傳輸變慢的傳輸變得快起來,但卻不能讓那些鏈路質量原本沒有問題的變得更快。

除此之外還有一個優化點,就是 TCP Pacing。
前文我們已經講過,TCP 是通過 CWND/RTT 來控制傳輸速率的,在一個 RTT 中,最多只能發 min(CWND, RWND) 這么多數據。但是 TCP 協議棧在發送數據時,是在 RTT 周期之初一股腦將數據發送出去的,這樣宏觀看沒有任何問題,但如果微觀看,數據發送波形就像上圖那樣,一個又一個的凸起。雖然在 RTT 單位時間內發送量恒定,但某微觀時間線上的發送速率確實超級猛烈的,這樣有可能造成瞬間鏈路擁塞(尤其是窄帶線路)。

原文請參考: https://homes.cs.washington.edu/~tom/pubs/pacing.pdf

通過 TCP 三次握手建連可以測得 RTT,在已知 CWND 的情況下,通過控制發包的時間間隔可以實現 Pacing 效果,使數據包在圍觀看是均衡發送充滿整個 RTT 空間的效果,這樣可以避免瞬時擁塞,對窄帶鏈路后需要勻速恒定傳輸的業務非常有效。

除了 Pacing 以外,還有很多不同的優化算法或策略: 建連優化:TCP 在建立連接時,如果丟包,會進入重試,重試時間是 1s、2s、4s、8s 的指數遞增間隔,縮短定時器可以讓 TCP 在丟包環境建連時間更快,非常適用于高并發短連接的業務場景。 首包優化:此優化其實沒什么實質意義,若要說一定會有意義的話,可能就是滿足一些評測標準的需要吧,例如有些客戶以首包時間作為性能評判的一個依據。所謂首包時間,簡單解釋就是從 HTTP Client 發出 GET 請求開始計時,到收到 HTTP 響應的時間。為此,Server 端可以通過 TCP_NODELAY 讓服務器先吐出 HTTP 頭,再吐出實際內容(分包發送,原本是粘到一起的),來進行提速和優化。據說更有甚者先讓服務器無條件返回 "HTTP/" 這幾個字符,然后再去 upstream 拿數據。這種做法在真實場景中沒有任何幫助,只能欺騙一下探測者罷了,因此還沒見過有直接發 "HTTP/" 的,其實是一種作弊行為。
平滑發包:如前文所述,在 RTT 內均勻發包,規避微分時間內的流量突發,盡量避免瞬間擁塞,此處不再贅述。 丟包預判:有些網絡的丟包是有規律性的,例如每隔一段時間出現一次丟包,例如每次丟包都連續丟幾個等,如果程序能自動發現這個規律(有些不明顯),就可以針對性提前多發數據,減少重傳時間、提高有效發包率。 RTO 探測:如前文講 TCP 基礎時說過的,若始終收不到 ACK 報文,則需要觸發 RTO 定時器。RTO 定時器一般都時間非常長,會浪費很多等待時間,而且一旦 RTO,CWND 就會驟降(標準 TCP),因此利用 Probe 提前與 RTO 去試探,可以規避由于 ACK 報文丟失而導致的速度下降問題。 帶寬評估:通過單位時間內收到的 ACK 或 SACK 信息可以得知客戶端有效接收速率,通過這個速率可以更合理的控制發包速度。 帶寬爭搶:有些場景(例如合租)是大家互相擠占帶寬的,假如你和室友各 1Mbps 的速度看電影,會把 2Mbps 出口占滿,而如果一共有 3 個人看,則沒人只能分到 1/3。若此時你的流量流量達到 2Mbps,而他倆還都是 1Mbps,則你至少仍可以分到 2/(2+1+1) * 2Mbps = 1Mbps 的 50% 的帶寬,甚至更多,代價就是服務器側的出口流量加大,增加成本。(TCP 優化的本質就是用帶寬換用戶體驗感) 鏈路質量記憶:如果一個 Client IP 或一個 C 段 Network,若已經得知了網絡質量規律(例如 CWND 多大合適,丟包規律是怎樣的等),就可以在下次連接時,優先使用歷史經驗值,取消慢啟動環節直接進入告訴發包狀態,以提升客戶端接收數據速率。

之前講的 TCP 優化都是需要去修改代碼的,這里有一個不用修改代碼的方法,僅修改參數就可以。
內核協議棧參數 net.ipv4.tcp_slow_start_after_idle 默認是開啟的,這個參數的用途,是為了規避 CWND 無休止增長,因此在連接不斷開,但一段時間不傳輸數據的話,就將 CWND 收斂到 initcwnd,kernel-2.6.32 是 10,kernel-2.6.18 是 2。因此在 HTTP Connection: keep-alive 的環境下,若連續兩個 GET 請求之間存在一定時間間隔,則此時服務器端會降低 CWND 到初始值,當 Client 再次發起 GET 后,服務器會重新進入慢啟動流程。
這種友善的保護機制,對于 CDN 來說是幫倒忙,因此我們可以通過命令將此功能關閉,以提高 HTTP Connection: keep-alive 環境下的用戶體驗感。 # sysctl net.ipv4.tcp_slow_start_after_idle=0
原文鏈接
本文為云棲社區原創內容,未經允許不得轉載。

科技資訊:

科技學院:

科技百科:

科技書籍:

網站大全:

軟件大全:

熱門排行
女人个人私人电话联系杭州的|热久久久久香蕉无品码|爱情岛亚洲永久自拍品质|国产丶欧美丶日本不卡