最近生產上出現一個性能問題,表現爲:行情延時5s左右。從log一路追查下去,發現是咱們本身寫的一個行情網關(部署在xx.xx.xx.132)<->第三方的中轉網關(部署在xx.xx.xx.133)之間的通訊產生的。網絡
Who to blame? 這是個問題,是咱們的行情網關、網絡、仍是第三方的中轉網關。因此想到用WireShark抓包進行分析。抓到的包在這裏:CaptureData-20160905.pcapng,用WireShark打開後,在統計裏有不少有用的信息,有用的是這幾個:tcp
- 捕獲文件屬性:能看到基本信息,抓包起始時間、跨度(01:04,共64秒)、大小(7624KB)、分組(28068個包)等
- 協議分級:能看到各級協議的包的佔比
- IO圖表:能看到每秒的包數量,還能夠自定義過濾器,對Y軸加一些sum、count、avg等統計方法
- TCP-時間序列:很能反映通訊特徵,任何一方的seq不變表示再也不發數據,只發長度爲0的應答包
- TCP-吞吐量:反映每秒吞吐的包長度
- TCP-往返時間:rtt round trip time, 這個圖很能說明132處理的快,133發的慢
- TCP-窗口尺寸:表示一方接收數據的能力,132一直在5萬以上,而133到過0
首先要設置合適的過濾器,過濾出咱們感興趣的包,試下來最有用的是:ip.addr == xx.xx.xx.132 && ip.addr == xx.xx.xx.133。經過分析,整個60秒的通訊過程分爲3個部分:性能
- 132:50012端口與133:7777端口的3次握手,syn->syn ack->ack。創建鏈接後,狀態變爲established
- 132:50013端口向133:7777端口發送數據,主要是發送要訂閱的標的。在最下面的data窗口能看到ascii碼裏會顯示標的的代碼,好比au1609等
- 132:50013端口接收133:7777端口發來的數據,主要是期貨行情。
分析的一些小結論以下:this
- 數據的邏輯關係:
發送端seq + data bytes = 接收端ack
以及 發送端seq + data bytes = 發送端next seq
- 接收端有時會將若干個ack確認包合併成1個。
- 包15281到15673,注意到133的windowSize一直在不斷減小,忽然變大就是window update。包16073開始各類window full、zero window,由於133的winSize=0滿了,132開始發送0窗口探測報文。訂閱完成後133的win就再也不減小了,沒壓力了。換成133給132發送行情數據了。
- Frame在網線級別,Ethernet在mac級別,IP在IP地址(v四、v6)級別,tcp在端口port級別。
- 注意前兩次握手syn和syn ack裏有關於Selective Ack、Maximum Segment Size和Windows Scale(好比:8,表示位移8位,即乘數爲256)等選項的協商
- 吞吐量(bytes/sec) = Window Size(bytes) / RTT(round trip time, sec) = 64KB/0.000128s = 500MB/s
- 右鍵Follow this stream,會產生一個過濾器:tcp.stream eq 604,其實對應於每一個ip+port對都會產生一個stream index,不論方向。這個index應該是wireshark在抓取過程當中順序產生的,相似於Frame Number。這個過濾器的效果相似於:ip.addr == xx.xx.xx.132 && ip.addr == xx.xx.xx.133 && tcp.port == 7777 && tcp.port == 50012,仍是蠻方便實用的。
- 性能分析:syn、ack在tcp協議級別,不包括任何數據,與應用層無關,握手不卡說明網絡沒問題。發送行情的過程當中,雙方的win=65535,表示窗口這塊都有富餘,雙方的網絡都不卡。132收到行情處理再回復ack只用了<0.1ms,說明接收端的速度也很快。因此只能有一個解釋,133發送端發的慢。其實從133的日誌裏也能看出來,「客戶端發送隊列已滿,將丟棄xx報文」。
- 因爲中轉網關是第三方的程序,咱們無法控制,所以只能咱們減小訂閱的標的數,發送的壓力小了,天然就不慢了。