為了簡化說明這個問題,我們可以將問題抽象如下:
1) 有乙個http伺服器,提供乙個處理post請求的handler,這個請求裡面,可以簡化認為什麼都不做,只是讀取客戶端的request body就直接返回了。
2) http客戶端傳送了乙個post請求, body大概是500kb左右。
3) 客戶端和伺服器處在兩個資料中心,它們之間的時延大概在20ms左右。
但問題是:明明在handler裡面除了列印一下body什麼也沒做,為什麼handler卻花了100ms左右。
那這100ms究竟花在了**呢?wireshark抓包看一下:
10.0.0.83 是客戶端ip,10.0.4.166是伺服器端ip。可以發現每隔一段時間(紅色部分),傳送端會出現一次0.02s左右的時延。一共出現了5次,因此有了100+ms的時延。
下圖是tcp seq num的增長曲線統計資訊:
從這張圖,看到tcp的seq num有明顯的stepping,每次stepping都等待了20ms左右,而這個時間正是乙個rtt的時間。
再看tcp window scaling:
從圖中的windows size的變化可以看出,在每次rtt之後window scaling就大概增長一倍,而這種增長,正是tcp慢啟動的過程(慢啟動過程中每次rtt會增加一倍的window size)。
快速複習一下tcp的慢啟動過程:
tcp在三次握手之後,便會傳送資料報,但是此時tcp並不清楚客戶端和伺服器端的時延/頻寬狀況,它應該傳送多少資料比較合理呢?tcp有個探測網路的過程,這個過程會採用慢啟動策略。根據這個策略,客戶端每次收到伺服器端的ack時,就將傳送視窗設定為上一次的兩倍。假設初始視窗大小為x,然後傳送端會傳送x個位元組,當傳送端收到服務端的ack時,傳送端就會把視窗大小設定為2倍,然後繼續傳送,下次再收到ack時,就將傳送視窗提高到4倍。保持這種指數增長直到達到ssthresh。tcp本身還有很多細節,本文暫且先放一放這裡的細節。
回過頭來看這個慢啟動問題,解決這個問題一般有兩種思路:
1) 短連線改為長連線。如果改為tcp連線,那不需要每次都建立連線,這樣自然就沒有慢啟動過程。
2)加速啟動過程。可以通過調整初始initcwnd/initrwnd(修改tcp的初始視窗大小),以及接收/傳送端的tcp send/receive buffer大小,從而提高跨資料中心/高延遲時在tcp慢啟動過程中傳輸效能。
第二種方式,具體引數可以根據實際情況調整。以下只是乙個修改示例:
增加初始初始window(預設為10倍的mss):
ip route change default via *** initcwnd 100 initrwnd 100
增大send/receive buffer:
net.core.wmem_max=12582912
net.core.wmem_default=12582912
net.core.rmem_max=12582912
net.core.rmem_default=12582912
net.ipv4.tcp_rmem= 102400 873800 12582912
net.ipv4.tcp_wmem= 102400 873800 12582912
總結:1) wireshark分析tcp問題時,可以借助tcptrace檢視是否有stepping存在,如果存在stepping,一般都有tcp buffer問題/tcp視窗大小相關的問題。
2) tcp短連線存在慢啟動限制,如果傳輸body不大的情況下,沒太大感知,但是如果body又比較大,又是短連線,此時傳輸效率不高。linux 預設配置對於相同資料中心的tcp連線來說,如果不是傳輸特別大,一般沒有太大問題,因為dc內部的時延都非常小,通常在1ms以內。但對於時延較大時,預設引數需要調整,否則可能存在效能問題。
3)tcp有很多細節值得關注,特別是在有延遲/網路頻寬不穩定的情況下。
關於TCP三次握手?二次握手為什麼不行?
zz 關於tcp三次握手?二次握手為什麼不行?1 tcp的三次握手過程 主機a向b傳送連線請求 主機b對收到的主機a的報文段進行確認 主機a再次對主機b的確認進行確認。2 採用三次握手是為了防止失效的連線請求報文段突然又傳送到主機b,因而產生錯誤。失效的連線請求報文段是指 主機a發出的連線請求沒有收...
記一次sql二次注入
簡單的說,二次注入是指已儲存 資料庫 檔案 的使用者輸入被讀取後再次進入到 sql 查詢語句中導致的注入。相比於直接注入,二次注入是比較有趣的。因為他會把你第一次的請求儲存,然後在第二次使用到的時候,才會啟用並且返回結果。例如在某個插入功能中,我們插入構造的sql語句,此時並沒有什麼現象,但是當瀏覽...
與TCP的第一次握手
通訊的學習是從寫伺服器開始的,之後加上客戶端,然後實現兩個之間的訊息傳送,這其實是基於tcp ip的協議的通訊,跟之前看到的udp協議不同,是一種面向連線,需要通訊雙方建立連線並確認後才能實現資料的傳輸。這樣的話,tcp的資料傳輸比udp更安全可靠。面向連線的傳輸是以兩個主機間的握手開始的,乙個主機...