真刀真槍壓測:基於TCPCopy的仿真壓測方案

鄭昀 基於劉勤紅和石雍志的實踐報告 建立於2015/8/13 最後更新於2015/8/19
關鍵詞:壓測、TCPCopy、仿真測試、實時拷貝流量

本文檔適用人員:技術人員
提綱:
  1. 爲何要作仿真測試
  2. TCPCopy是如何工做的
  3. 實做:仿真測試的拓撲
  4. 實做:操做步驟
  5. 可能會遇到的問題
    1. ip_conntrack
    2. 少許丟包
    3. 離線重放
    4. 不提取7層信息
  6. 觀測的性能指標

0x00,爲何要作仿真測試
線下的傳統壓力測試,難以模擬真實流量,尤爲難以模擬正常流量混雜着各色異常流量。因此,線下壓得好好的系統,上線後可能某天忽然雪崩, 說好能支撐 5 倍流量的系統重構,也許流量一翻倍就完全掛了。
但辦法總比問題多。
系統重構或重要變動上線前,能夠拷貝線上真實流量,實時模擬線上流量,甚至能夠放大真實流量,進行壓力測試,以評估系統承載能力。
反過來也能夠這樣,若是線上跑着跑着發現有性能瓶頸,但線下環境難以復現,還不如把真實流量拷貝到線下重放,畢竟線下環境便於上各類排查手段,重放幾遍都行,直到找到問題。
因此本次基於 Varnish 的商品詳情頁靜態化在上線前,作了仿真壓測。
 
如何實時拷貝線上真實流量呢?
TCPCopy。

2010年,網易技術部的王斌在王波的工做基礎上開發了 TCPCopy - A TCP Stream Replay Tool。2011年9月開源。當前版本號是 1.0.0。不少公司的模擬在線測試都是基於 TCPCopy 作的,如一淘html

TCPCopy 是一種請求複製(複製基於 TCP 的 packets)工具 ,經過複製在線數據包,修改 TCP/IP 頭部信息,發送給測試服務器,達到欺騙測試服務器的TCP 程序的目的,從而爲欺騙上層應用打下堅實基礎。
 
0x01,TCPCopy是如何工做的
王斌講過,基於 Server 的請求回放領域,通常分爲離線回放和在線實時複製兩種。
其中請求實時複製,通常能夠分爲兩類:
1)基於應用層的請求複製 ,
2)基於底層數據包的請求複製。
 
若是從應用層面進行復制,好比基於服務器的請求複製,實現起來相對簡單,但也存在着若干缺點:
1)請求複製從應用層出發,穿透整個協議棧,這樣就容易擠佔應用的資源,好比寶貴的鏈接資源 ,
2)測試跟實際應用耦合在一塊兒,容易影響在線系統,
3)也所以很難支撐壓力大的請求複製,
4)很難控制網絡延遲。
而基於底層數據包的請求複製,能夠作到無需穿透整個協議棧,路程最短的,能夠從數據鏈路層抓請求包,從數據鏈路層發包,路程通常的,能夠在IP層抓請求包,從IP層發出去,無論怎麼走,只要不走TCP,對在線的影響就會小得多。這也就是 TCPCopy 的基本思路。
 
從傳統架構的 rawsocket+iptable+netlink,到新架構的 pacp+route,它經歷了三次架構調整,現現在的 TCPCopy 分爲三個角色:
  • Online Server(OS):上面要部署 TCPCopy,從數據鏈路層(pcap 接口)抓請求數據包,發包是從IP層發出去;
  • Test Server(TS):最新的架構調整把 intercept 的工做從 TS 中 offload 出來。TS 設置路由信息,把 被測應用 的須要被捕獲的響應數據包信息路由到 AS;
  • Assistant Server(AS):這是一臺獨立的輔助服務器,原則上必定要用同網段的一臺閒置服務器來充當輔助服務器。AS 在數據鏈路層截獲到響應包,從中抽取出有用的信息,再返回給相應的 OS 上的 tcpcopy 進程。
 
請配合下圖1理解:
圖1 三個角色的數據流轉方式
 
Online Server 上的抓包:
tcpcopy 的新架構在 OS 上抓請求數據包默認採用 raw socket input 接口抓包。王斌則推薦採用 pcap 抓包,安裝命令以下: 
./configure --enable-advanced --enable-pcap
  make
  make install
這樣就能夠在內核態進行過濾,不然只能在用戶態進行包的過濾,並且在 intercept 端或者 tcpcopy 端設置 filter(經過 -F 參數,相似 tcpdump 的 filter),達到起多個實例來共同完成抓包的工做,這樣可擴展性就更強,適合於超級高併發的場合。

爲了便於理解 pcap 抓包,下面簡單描述一下 libpcap 的工做原理。 nginx

一個包的捕捉分爲三個主要部分: git

  1. 面向底層包捕獲,
  2. 面向中間層的數據包過濾,
  3. 面向應用層的用戶接口。

 

這與 Linux 操做系統對數據包的處理流程是相同的(網卡->網卡驅動->數據鏈路層->IP層->傳輸層->應用程序)。包捕獲機制是在數據鏈路層增長一個旁路處理(並不干擾系統自身的網絡協議棧的處理),對發送和接收的數據包經過Linux內核作過濾和緩衝處理,最後直接傳遞給上層應用程序。以下圖2所示: github

libpcap的三部分

圖2 libpcap的三部分
 
Online Server 上的發包:
如圖1所示,新架構和傳統架構同樣,OS 默認使用 raw socket output 接口發包,此時發包命令以下: 
./tcpcopy -x 80-測試機IP:測試機應用端口 -s 服務器IP -i eth0
其中 -i 參數指定 pcap 從哪一個網卡抓取請求包。
此外,新架構還支持經過 pcap_inject(編譯時候增長--enable-dlinject)來發包。
 
Test Server 上的響應包路由:
須要在 Test Server 上添加靜態路由,確保被測試應用程序的響應包路由到輔助測試服務器,而不是回包給 Online Server。
 
Assistant Server 上的捕獲響應包:
輔助服務器要確保沒有開啓路由模式 cat /proc/sys/net/ipv4/ip_forward,爲0表示沒有開啓。
輔助服務器上的 intercept 進程經過 pcap 抓取測試機應用程序的響應包,將頭部抽取後發送給 Online Server 上的 tcpcopy 進程,從而完成一次請求的複製。
 
0x02,實做:仿真測試的拓撲
下面將列出本次仿真測試的線上環境拓撲圖。
環境以下:
  • Online Server
    • 4個生產環境 Nginx
      • 172.16.***.110
      • 172.16.***.111
      • 172.16.***.112
      • 172.16.***.113
  • Test Server
    • 一個鏡像環境的 Nginx
      • 172.16.***.52
  • Assistant Server
    • 鏡像環境裏的一臺獨立服務器
      • 172.16.***.53
拓撲如圖3所示:
壓測環境拓撲
圖3 壓測環境拓撲
它的數據流轉順序以下圖4所示:
壓測環境的數據流轉順序
圖4 壓測環境的數據流轉順序
 
0x03,實做:操做步驟
下面分別列出在 Online Server/Test Server/Assistant Server 上的操做步驟。
3.1 Online Server 上的操做:
下載並安裝 tcpcopy 客戶端;
git clone http://github.com/session-replay-tools/tcpcopy
./configure
make && make install
  
安裝完成後的各結構目錄:
Configuration summary
 
  tcpcopy path prefix: "/usr/local/tcpcopy"
  tcpcopy binary file: "/usr/local/tcpcopy/sbin/tcpcopy"
  tcpcopy configuration prefix: "/usr/local/tcpcopy/conf"
  tcpcopy configuration file: "/usr/local/tcpcopy/conf/plugin.conf"
  tcpcopy pid file: "/usr/local/tcpcopy/logs/tcpcopy.pid"
  tcpcopy error log file: "/usr/local/tcpcopy/logs/error_tcpcopy.log"
  
運行 tcpcopy 客戶端,有幾種可選方式:
./tcpcopy -x 80-172.16.***.52:80 -s 172.16.***.53 -d       #全流量複製
./tcpcopy -x 80-172.16.***.52:80 -s 172.16.***.53 -r 20 -d  #複製20%的流量
./tcpcopy -x 80-172.16.***.52:80 -s 172.16.***.53 -n 2 -d    #放大2倍流量
 
3.2 Test Server 上的操做:
添加靜態路由:
route add -net 0.0.0.0/0 gw 172.16.***.53
 
3.3 Assistant Server 上的操做:
下載並安裝 intercept 服務端;
git clone http://github.com/session-replay-tools/intercept
./configure
make && make install
 
安裝完成後的各結構目錄:
Configuration summary
  intercept path prefix: "/usr/local/intercept"
  intercept binary file: "/usr/local/intercept/sbin/intercept"
  intercept configuration prefix: "/usr/local"
  intercept configuration file: "/usr/local/intercept/"
  intercept pid file: "/usr/local/intercept/logs/intercept.pid"
  intercept error log file: "/usr/local/intercept/logs/error_intercept.log"
 
運行 intercept 服務端;
./intercept -i eth0 -F 'tcp and src port 80' -d
 
生產環境和鏡像環境數據傳輸流程圖
圖5 生產環境和鏡像環境數據傳輸流程圖
對照上圖5,再簡單解釋一下工做原理:
  1. TCPcopy 從數據鏈路層 copy 端口請求,而後更改目的 ip 和目的端口。
  2. 將修改過的數據包傳送給數據鏈路層,而且保持 tcp 鏈接請求。
  3. 經過數據鏈路層從 online server 發送到 test server。
  4. 在數據鏈路層解封裝後到達 nginx 響應的服務端口。
  5. 等用戶請求的數據返回結果後,回包走數據鏈路層。
  6. 經過數據鏈路層將返回的結果從 test server 發送到 assistant server。注:test server 只有一條默認路由指向 assistant server。
  7. 數據到達 assistant server 後被 intercept 進程截獲。
  8. 過濾相關信息將請求狀態發送給 online server 的 tcpcopy,關閉 tcp 鏈接。
0x04,可能會遇到的問題
王斌本身講:要想用好 tcpcopy,須要熟悉系統知識,包括如何高效率抓包,如何定位系統瓶頸,如何部署測試應用系統,如何抓包分析。常見問題有:1)部署測試系統不到位,耦合線上系統,2)忽視系統瓶頸問題,3)不知道如何定位問題,4)資源不到位,資源緊張引起的問題 。
 
1)ip_conntrack
2014年6月,微博的唐福林曾說:「Tcpcopy 引流工具是線上問題排查的絕佳之選,但使用者不多有人去關注開啓 tcpcopy 服務時,同時會開啓 ip_conntrack 內核模塊,這個模塊負責追蹤全部 tcp 連接的狀態,並且它的內部存儲有長度限制,一旦超過,全部新建連接都會失敗。」
王斌則 迴應說:「開啓 tcpcopy,自身不會去開啓 ip_conntrack 內核模塊。開不開啓 ip_conntrack 內核模塊,是用戶本身決定的,跟 tcpcopy 不要緊。」他 還建議:「 當鏈接數量很是多的時候,自己就應該關閉 ip_conntrack,不然嚴重影響性能。至於 tcpcopy,默認是從 ip 層發包的,因此也會被 ip_conntrack 干涉,文檔中也有描述,其實也能夠採用 --enable-dlinject 來發包,避開ip層的ip_conntrack。若是沒有報「ip_conntrack: table full, dropping packet」,通常無需去操心ip_conntrack。」以及「線上鏈接很少的場合,開啓 ip_conntrack 並無問題。線上鏈接比較多的場合,最好關閉 ip_conntrack,或者對線上應用系統端口設置 NOTRACK,至少我周圍的系統都是這樣的,這是爲性能考慮,也是一種好的運維習慣。」
 
2)少許丟包
如何發現 TCPCopy 丟包多仍是少呢?
王斌本身稱,在某些場景下,pcap 抓包丟包率會遠高於 raw socket 抓包,所以最好利用 pf_ring 來輔助或者採用 raw socket 來抓包。
丟包率須要在測試環境中按照定量請求發送進行對比才能展開計算,另外還須要對日誌內容進行分析,有待測試。
 

3)離線重放 redis

tcpcopy 有兩種工做模式:
1)實時拷貝數據包;
2)經過使用 tcpdump 等抓包生成的文件進行離線(offline)請求重放。
本次仿真測試,沒有試驗成功第二種工做模式,留待之後進一步研究。
 
4)不提取 7 層信息
會議上曾提出按域名區分拷貝流量,免得把不在本次壓測範圍內的工程打掛,但 tcpcopy 的原理是在 ip 層拷貝,不提取 7 層的信息,也就是說,在咱們的 Nginx*4 上部署 TCPCopy,只能是將全部流量拷貝到鏡像環境的 Nginx 上。反正沒有配置對應的 server,或者 server 停掉,這種處理不了的流量就丟棄掉。
 
0x05,觀測的性能指標
仿真壓測時,須要記錄下 Test Server 以及後端各類被壓工程的性能指標。
本次壓測,咱們記錄的指標有:
  • Java 工程的訪問次數,響應時間,平均響應時間,調用成功或失敗,Web端口鏈接數;
  • Web容器的 thread、memory 等狀況;
  • 虛擬機的 CPU-usage、Load-avg、io-usage 等;
  • memcached/redis 等緩存集羣的命中率等;
參考資源:
3, 王斌的微博
4,2013, tcpcopy架構漫談
 

-EOF- 後端

歡迎訂閱個人微信訂閱號『老兵筆記』,請掃描二維碼關注:
老兵筆記訂閱號二維碼
相關文章
相關標籤/搜索