原文: https://jkchao.cn/article/5a2...
TCP 負責在不可靠的傳輸信道之上提供可靠的抽象層,嚮應用層隱藏了大多數網絡通訊的複雜性能,好比丟包重發、按需發送、擁塞控制及避免、數據完整,等等。採用 TCP 數據流能夠確保發送的全部字節可以完整地被接收到,並且客戶端的順序也同樣。算法
可是 TCP 設計並未過多顧及時間,由此給瀏覽器 Web 性能帶來了挑戰。瀏覽器
全部 TCP 鏈接一開始都必須通過三次握手。客戶端與服務器在交換應用數據以前,必須就起始分組序列號,以及其餘一些鏈接相關的細節達成一致。處於安全考慮,序列號由兩端隨機生成。緩存
客戶端選擇一個隨機序列號 x,併發送一個 SYN 分組,其中可能還包含 TCP 標誌和選項。安全
服務器給 x 加 1,並選擇本身的一個隨機序列號 y,追加本身的標誌和選項,而後返回響應。服務器
客戶端給 x 和 y 加 1,併發送握手期間的最後一個 ACK 分組。cookie
客戶端能夠在發送 ACK 分組以後當即發送數據,而服務器必須等接收到 ACK 分組以後發送數據。網絡
每一個 TCP 鏈接都要通過三次握手,假若客戶端與服務器距離過長,會形成很是大的性能影響。於是,提高 TCP 性能關鍵在於想辦法重用鏈接。併發
爲解決這個問題,人們在積極尋找各類方案,其中長連接(Keep-Alive)、負載均衡、TFO(tcp fast open)即是其中的一些解決辦法。負載均衡
Keep-Alive,HTTP 1.1 以後默認開啓,指在一個 TCP 鏈接中能夠持續發送多份數據而不會斷開鏈接。tcp
基本原理:客戶端(如:ClientA)與負載均衡設備之間進行三次握手併發送 HTTP 請求。負載均衡設備收到請求後,會檢測服務器是否存在空閒的長連接,若是不存在,服務器將創建一個新鏈接。當 HTTP 請求響應完成後,客戶端與負載均衡設備協商關閉鏈接,而負載均衡則保持與服務器之間的這個鏈接。當有其餘客戶端(如:ClientB)須要發送 HTTP 請求時,負載均衡設備會直接向服務器之間保持的這個空閒鏈接發送 HTTP 請求,避免來因爲新建 TCP 鏈接形成的延時和服務器資源耗費。
儘管開啓了長連接,但是依然有35%的請求是從新發起一條鏈接,而握手會形成必定的延遲,TFO 的目標就是爲了去除這個延遲,在三次握手期間也能交換數據。
基本原理:
擁塞:即對供不該求,對資源的需求超過了可用的資源,網絡性能降低,整個網絡的吞吐量隨之負荷的增大而減少,甚至會發生擁塞崩潰的現象。
爲了減緩網絡擁塞現象,TCP 加入許多機制用來控制雙向發送數據的速度。如流量監控、擁塞控制、擁塞預防機制等。
流量控制是一種預防發送端過多向接收端發送數據的機制。
滑動窗口是實現流量控制的一種方法,一個簡單例子:
設 A 向 B 發送數據。在創建鏈接時,B 告訴了 A:「個人接收窗口值 rwnd = 400「 (rwnd: receiver window),所以,發送方的發送窗口不能超過接收方給出的接收窗口的數值。TCP 窗口的單位時字節,並非報文段。設每一個報文段的字節長 100,而數據報文段序號的初始值爲 1,大寫 ACK 表示首部中的確認位 ACK,小寫 ack 表示確認字段的值 ack。
從圖中能夠看出,B 進行了三次流量控制。第一次把窗口減小到 rwnd = 300,第二次又減小到了 rwnd = 100,最後減到 rwnd = 0,即不容許發送數據了。
當 rwnd = 0 時,則意味着必須由應用層先清空緩存區,才能接收剩餘數據。這個過程貫穿於每一個 TCP 鏈接的整個生命週期:每一個 ACK 分組都會攜帶相應的最新的 rwnd 值,以便兩端動態調整數據流,使之適應發送端和接收段的容量及處理能力。
儘管流量監控能夠防止發送端向接收端過多發送數據,可是發送端和接收端在鏈接創建之初,並不知道可用帶寬是多少,所以須要一個估算機制,而後還能夠根據網絡中不斷變化的條件而動態改變速度。
擁塞控制:防止過多的數據注入到網絡中,這樣可使網絡中的路由器或鏈路不致於過載。
慢啓動是實現擁塞控制的一種方法,此外還有擁塞預防、快速重發和快速恢復。
慢啓動,便是在分組被肯定之後,增大窗口大小,慢慢啓動。
具體實現以下:
發送方經過 TCP 鏈接初始化並維護一個擁塞窗口變量(cwnd)。並規定發送端與接收端之間最大能夠傳輸的數據量爲接收窗口(rwnd)與擁塞窗口(rwnd)的最小值。
cwnd 最初的值只有一個 TCP 段,1999年提高至 4 個 TCP 段,2013年,提高至 10 個 TCP 段。
因爲慢啓動的設計,限制了可用的吞吐量。對於大型流式下載服務的影響倒不顯著,可是對於小文件的傳輸卻很是不利,經常會出現尚未達到最大窗口請求就被終止的狀況。
簡單演示三次握手與慢啓動對簡單 HTTP 傳輸的影響。
鏈接參數:
當再次發送相同請求時:
慢啓用使用 cwnd 做爲起始值發送數據量,隨後成倍增加。直到超過接收系統配置的擁塞閾值(ssthresh)窗口,或者發生分組丟失現象,此時擁塞預防算法介入。
因爲已經發生擁堵,必須採起刪包措施。須要從新調整 cwnd 大小,此後擁塞預防按照本身的算法來增大 cwnd 以免丟包。若再次丟包,則從頭開始。