天天看點

TCPcopy:分布式TCP壓力測試工具

線下的傳統壓力測試,難以模拟真實流量,尤其難以模拟正常流量混雜着各色異常流量。是以,線下壓得好好的系統,上線後可能某天突然雪崩,說好能支撐 5 倍流量的系統重構,也許流量一翻倍就徹底挂了。

但辦法總比問題多。

系統重構或重要變更上線前,可以拷貝線上真實流量,實時模拟線上流量,甚至可以放大真實流量,進行壓力測試,以評估系統承載能力。

反過來也可以這樣,如果線上跑着跑着發現有性能瓶頸,但線下環境難以複現,還不如把真實流量拷貝到線下重放,畢竟線下環境便于上各種排查手段,重放幾遍都行,直到找到問題。

如何實時拷貝線上真實流量呢?TCPCopy

2010年,網易技術部的王斌在王波的工作基礎上開發了 TCPCopy - A TCP Stream Replay Tool。2011年9月開源。目前版本号是 1.0.0。很多公司的模拟線上測試都是基于 TCPCopy 做的,如一淘。

TCPCopy 是一種請求複制(複制基于 TCP 的 packets)工具 ,通過複制線上資料包,修改 TCP/IP 頭部資訊,發送給測試伺服器,達到欺騙測試伺服器的TCP 程式的目的,進而為欺騙上層應用打下堅實基礎。

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 程序。

tcpcopy項目位址:https://github.com/session-replay-tools/tcpcopy

Online Server 上的抓包:

tcpcopy 的新架構在 OS 上抓請求資料包預設采用 raw socket input 接口抓包。王斌則推薦采用 pcap 抓包,安裝指令如下:

yum install libpcap-devel

git clone git://github.com/session-replay-tools/tcpcopy.git

cd tcpcopy

./configure

make

make install

這樣就可以在核心态進行過濾,否則隻能在使用者态進行包的過濾,而且在 intercept 端或者 tcpcopy 端設定 filter(通過 -F 參數,類似 tcpdump 的 filter),達到起多個執行個體來共同完成抓包的工作,這樣可擴充性就更強,适合于超級高并發的場合。

為了便于了解 pcap 抓包,下面簡單描述一下 libpcap 的工作原理。

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

面向底層包捕獲,

面向中間層的資料包過濾,

面向應用層的使用者接口。

這與 Linux 作業系統對資料包的處理流程是相同的(網卡->網卡驅動->資料鍊路層->IP層->傳輸層->應用程式)。包捕獲機制是在資料鍊路層增加一個旁路處理(并不幹擾系統自身的網絡協定棧的處理),對發送和接收的資料包通過Linux核心做過濾和緩沖處理,最後直接傳遞給上層應用程式。如下圖2所示:

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 程序,進而完成一次請求的複制。

實驗

1.機器别表

192.168.0.11 -- onlie server

192.168.0.12 -- test server

192.168.0.13 -- Assistant server

2.online server操作

安裝tcpcopy

啟動TCPCOPY

./sbin/tcpcopy -x 80-192.168.0.12:80 -s 192.168.0.13 -c 192.168.0.11

-x 參數指定本機哪個端口的流量轉發到哪台機器的哪個端口,格式為localip:80-targetip:port

-s 參數指定Assistant server -c 指定本機

可以添加-n參數來放大流量,比如說 -n 2 代表放大2倍流量

可以添加-r參數來複制一部分流量。比如說,-r 20 代表複制20%的流量

可以添加-d參數來讓tcpcopy背景運作

3.test server操作

route add host 192.168.0.11 gw 192.168.0.13

這一步很重要,之前我就是因為這個路由設定不正确,一直沒搭建成功

4.Assistant server操作

安裝intercept

git clone git://github.com/session-replay-tools/intercept.git

cd intercept

啟動intercept

./sbin/intercept -i eth0 -F tcp and src port 80 -d

-i 指定網卡

-F 指定copy的是tcp還是udp

-d 代表背景運作

我這裡預設online server還有test server都啟動了nginx。當你通路online server上的http服務的時候。你會發現test server上也有通路log存在。可以通過監控test server上的負載,來判斷機器的運作情況