Http協議承載了互聯網上的主要流量,然而說到傳輸,還要回歸到最基本的網絡分層模型TCP/IP。TCP/IP是全球計算機及網絡設備都在使用的一種經常使用的分組交互網絡分層協議集。客戶端能夠打開一條TCP/IP鏈接,與世界上的任何服務器進行數據交換,而且交換的數據永遠不會丟失,受損或失序。算法
下面是常見的TCP/IP分層協議,分爲安全與非安全版本。緩存
由圖可知,HTTP的整個傳輸過程能夠描述爲「HTTP over TCP over IP」。TCP是可靠地傳輸協議,就好像一條管道,從TCP鏈接一段填入的字節會從另一端以原有的順序,正確的傳送出來。安全
TCP層與IP層都有本身的協議,他們對數據的關注點不一樣。總的來講,TCP段包含了目的端口與源端口,用來創建程序之間的鏈接。IP段包含了目的IP與源IP,用來進行網絡尋址,最終創建機器之間的鏈接。而一條TCP鏈接正是根據這四點惟一對應的:服務器
<源IP地址,源端口號,目的IP地址,目的端口號>
不一樣的鏈接不能夠擁有徹底相同的四個屬性。對於通常功能而言,本身發起的鏈接中源端口號是隨機生成的。網絡
因爲http數據是經過TCP傳輸的,http鏈接的性能很大程度上取決於TCP通道的性能。咱們先分析一個正常的http事務。負載均衡
從上面的流程能夠看出來,真正的有業務意義的階段是「請求-處理-響應」,其餘階段時間消耗都是與業務無關的。所以能夠從這上面思考如何優化TCP性能。性能
TCP鏈接的性能一般從下面5個方面考慮:優化
從上面的圖中能夠看出,一次正常的交互須要通過DNS查詢、握手、揮手等與數據傳輸無關的操做。若是每次傳輸的數據都不多,那麼這種操做所佔用的比例就會增長,這將大大下降HTTP的性能。因爲HTTP是創建在TCP鏈接的基礎上的,因此握手的過程是對HTTP不可見的,HTTP只能看到創建鏈接發生了時延。三次握手的過程這裏不作贅述,感興趣的請查閱相關資料。操作系統
三次握手簡單來講是創建鏈接前的三次交互來確認鏈接能夠創建,有SYN,ACK+SYN,ACK三次報文通訊。對於一些小的HTTP事務,好比握手後告知頁面304了,這種事務中在TCP創建上可能會法費一半甚至更多的時間。code
解決方案:咱們能夠經過重用TCP鏈接來減小這種性能上的損失,好比持久鏈接。
因特網是沒法保證數據可靠傳輸的,由於在網絡路由超負荷的狀況下,容許丟棄任意網絡分組。因此,TCP實現了一套本身的確認機制來保障數據可靠傳輸。
每一個TCP段都有一個序號和數據校驗和,接受者在接受完整以後會向發送者送回確認分組,這樣保證了這個分組的可靠傳輸。若是發送者在必定時間窗口內沒有接收到響應的確認分組,則認爲這個分組已經丟失,對該分組進行重發。
因爲確認報文很小,因此TCP容許在發往相同方向的數據分組中對其進行「捎帶」,就是這種捎帶出了問題。TCP將返回確認信息與輸出信息集合在一塊兒,能夠有效的利用網絡鏈接。所以爲了找到相同方向的數據分組來進行捎帶,不少TCP棧實現了一種「延時確認」的算法。這種算法將確認信息放入緩衝區,在必定的時間窗口內(通常是100-200毫秒)找不到輸出分組,則對確認數據進行單獨發送。
若是請求響應並無較多的數據傳輸過程,則知足捎帶確認的可能性就很低。一般,延遲確認算法會引入至關大的時延。
解決方案:根據操做系統的不容,能夠調整或禁止延遲確認算法。
TCP傳輸過程有慢啓動與擁塞控制的概念。
TCP在創建鏈接開始的時候,會進行慢啓動,數據窗口會逐漸指數變大,在達到閾值後會線性增加。當發生某次超時以後,會迅速減少窗口到最小,從新開始慢啓動,通知減少以前的閾值。
在這種機制的保障下,一個TCP鏈接是會進行自我調整的,所以一個新的鏈接的傳輸效率是不如老鏈接的。
解決方案:咱們經過重用鏈接,可使得傳輸效率提高,好比持久鏈接。
Nagle算法與延時確認算法有些相似。不過Nagle算法關注的是發送方,爲了保證不大量發送小的數據報文形成3.1的問題。該算法鼓勵每次發送大的數據組,若是數據分組不夠大,則放在緩存區等待與其餘數據分組結合起來達到上限後一塊兒發送,或者其餘分組被確認後發送。
而對於一些小的數據分組而言,可能不少個也沒法攢夠一次發送的數量。當這時接收端也採用延時確認算法以後,事情就變得恐怖了。對於發送端而言,不少小的數據分組沒有成功發送,由於第一個分組發送以後,服務端進行了延時確認200ms,在這段時間過去以後發送端的第二個分組纔會被髮送,這樣的排隊阻塞簡直是噩夢。
解決方案:能夠在協議棧中設置TCP_NODELAY來禁用Nagle算法。
當一個TCP鏈接完成四次揮手關閉以後,會進入TIME_WAIT狀態,在等待2MSL以後會釋放該TCP鏈接。由於TCP的分組可能不是按照順序到達的,咱們假設一個分組在網絡中最多存貨1MSL,則2MSL以後基本上就能夠認爲確實結束了。若是在2MSL之間服務端沒有接收到LAST_ACK發送的FIN對應的響應,則TIME_WAIT會再次發送ACK。
以前有說過,一個TCP能夠經過下面四個屬性來確認。
<源IP地址,源端口號,目的IP地址,目的端口號>
而對於一個服務來講,以後源端口是不肯定的,由於每次源端口都是隨機生成的。可是源端口是有數量限制的,好比60000個端口,MSL是60秒。則鏈接速率就被限制在60000/120=500次/秒。若是不進行相關的優化,操做系統就沒法發起更多的鏈接。
解決方案:能夠增長請求端機器,經過負載均衡的方法下降端口耗盡的可能性,或者在服務端使用幾個虛擬IP增長鏈接的組合。
HTTP創建在TCP的基礎上,若是咱們在工做中發現HTTP創建鏈接的效率很低,能夠考慮從上面的五個角度分析是否達到了相關的瓶頸,並經過推薦方案解決問題。