流量複製方案對比:Tcpcopy vs Goreplay

文章首發公衆號「碼農吳先生」, 歡迎關注,及時獲取更多技術幹活~python

「流量複製」經常應用在準生產環境的測試中,將線上的流量複製到一個準生產環境服務中,測試新功能和服務的承壓能力。流量複製能夠徹底模擬線上的流量,對複雜的業務場景進行真實的服務測試,又不會對生產服務產生任何反作用。nginx

對於複雜的流量複製應用場景和需求,徹底能夠立項開發一套完整的複製架構,可參考字節團隊自研的 ByteCopy 項目。而對於一些簡單的需求,開源的工具基本能夠搞定。開源的流量複製工具備不少,經常使用的有 goreplay、tcpreplay、tcpcopy 等。git

本文主要來探討下 tcpcopy 和 goreplay 的方案實現,廢話很少說開整。github

tcpcopy 方案實現

tcpcopy 簡介

tcpcopy 由網易技術部王斌等開發,並於 2011 年 9 月開源的。tcpcopy 最新架構以下(來自做者王斌博客:blog.csdn.net/wangbin579/…golang

架構

tcpcopy 主要有兩個組件構成 tcpcopy client 和 intercept 。client 端負責複製流量和轉發,intercept 負責對迴應流量的攔截和 tcpcopy 的連接處理。ubuntu

tcpcopy 搭建

實例環境以下,下面來闡述下整個架構的搭建過程:bash

  • 192.168.33.11 生產服務器,部署 tcpcopy client
  • 192.168.33.12 輔助服務器,部署 intercept
  • 192.168.33.13 測試服務器

各組件可直接從 github 下載源碼包,編譯安裝:服務器

# 起壓機部署 tcpcopy client 192.168.33.11
wget https://github.com/session-replay-tools/tcpcopy/archive/1.0.0.tar.gz
tar xvf 1.0.0.tar.gz
cd tcpcopy-1.0.0
./configure --prefix=/opt/tcpcopy
make
make install

# 輔助機部署 intercept 192.168.33.12 , 截獲包須要依賴 libpcap 抓包函數庫
yum -y install libpcap-devel
# ubuntu
# apt install -y libpcap-dev
https://github.com/session-replay-tools/intercept/archive/1.0.0.tar.gz
tar xvf 1.0.0.tar.gz
cd intercept-1.0.0
./configure --prefix=/opt/tcpcopy/
make
make install
複製代碼

安裝完以後,先啓動 intercept,運行以下命令:markdown

/opt/tcpcopy/sbin/intercept -i enp0s8 -F 'tcp and src port 8000' -d
# -i,指定網卡 enp0s8
# -F,過濾,語法和pcap抓包工具一直,如tcpdump
# -d,以domain的形式啓動。
# 其餘參數可 -h 查看。
複製代碼

啓動 intercept 以後,再啓動 tcpcopy client 。tcpcopy 啓動依賴 intercept ,啓動時確保 intercept 啓動成功。網絡

/opt/tcpcopy/sbin/tcpcopy -x 8000-192.168.33.13:8000 -s 192.168.33.12 -c 192.168.1.x -n 2 -d
# -x,複製本地8000端口的流量,轉發到192.168.33.13機器的8000端口
# -s,輔助服務器intercept 地址
# -c,修改轉發包的原地址爲該地址段的地址,這裏也能夠是明確的ip。這個ip端用來假裝數據包,方便intercept作路由劫持。
# -n,流量倍數
# -d,以domain的形式運行
複製代碼

在測試服務器添加攔截路由,以下:

# 測試機 192.168.33.13
route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.33.12
複製代碼

該路由至關於把到 192.168.1.0 網段的包都走網關 192.168.33.12,對測試服務器的回包作僞地址攔截。

這即是 tcpcopy 的整個架構部署了。

包流動分析

下面咱們抓包看看這個過程當中包是如何流動的。

我在 tcpcopy client 機器 192.168.33.11 和測試機器 192.168.33.13 使用 python -m SimpleHTTPServer 分別起了一個 8000 端口的服務用來測試,從我本機 192.168.33.1 發送請求,在三臺機器上抓包。

tcpcopy client 機器 192.168.33.11 包信息以下:

tcpcopy

紅色標註塊爲我本機(192.168.33.1)和 tcpcopy client 機器(192.168.33.11)的正常請求交換,從三次握手,到 http 請求,到最後的斷鏈。

藍色標註塊則爲 tcpcopy 複製的流量,能夠看到爲了讓 intercepter 攔截回包流量,tcpcopy 已將包源 ip 地址替換爲咱們指定的僞網段(192.168.1.0)的地址,這樣在回包時,就會根據測試服務器上的路由將回包指向輔助服務器 intercept,避免對生產流量形成影響。這也是爲何複製流量三次握手和 http 都沒有回包的緣由。

看測試服務器 192.168.33.13 的包:

test server

測試服務器的包和正常流量包同樣,三次握手到 http 請求,最後斷連。這裏和測試服務器 192.168.33.13 交互的源地址 ip 已經被 tcpcopy 替換爲僞 ip 192.168.1.1 。

看 intercept 192.168.33.12 的包:

image

能夠看到輔助服務器攔截下來的請求,標註塊 1 爲複製流量三次握手時的回包,標註塊 2 爲 http 請求的回包,這即是 intercept 的攔截功能。能夠看到在標註塊 一、2 以後,輔助服務器(192.168.33.12)和 tcpcopy 服務器(192.168.33.11)進行了數據交換,這部分即是 intercept 的 tcp 處理功能,它把有用的信息返回給 tcpcopy 以便能使 tcpcopy 和測試機的 tcp 連接完成。

根據上邊抓包,咱們獲得了和架構圖同樣的包流動過程,總結以下:

  • 生產流量正常請求,服務正常回應。
  • tcpcopy 服務在生產機器上覆制流量,並修改流量包的源 ip 地址爲咱們指定的僞網絡段(-c 參數指定),以後將流量轉發到測試服務器。
  • 測試服務器,接受到流量,但包的源地址爲僞網絡段的地址,回包時根據提早配置好的僞路由,將回包導流到輔助服務器。
  • 輔助服務器接收測試服務器的回包,可是並不轉發。而是解包,只返回部分必要的信息給 tcpcopy,以便完成 tcpcopy 和測試服務器之間的 tcp 交互。

根據官方文檔,咱們還須要注意幾個問題:

  • 輔助服務器不作包的轉發,須要關閉內核參數 ip_forward
  • 在作測試時,注意上行流量的過濾和測試數據源的隔離,防止對生產數據形成屢次操做的影響。
  • 上邊爲在線實時的複製模式,tcpcopy 還支持離線方式,具體可查閱文檔
  • 輔助機須要和測試機在一個網段,以便輔助機做爲僞網段的網關使用。這裏能夠加一次代理,解除這個限制。如使用 nginx 做爲測試中起色,將僞路由添加到 nginx 服務器上,測試機只須要向 nginx 註冊便可,無需作其餘配置。

goreplay 方案實現

goreplay 簡介

Goreplay 是另外一個比較經常使用的流量複製開源工具。與 tcpcopy 相比它的架構更簡單,只有一個 gor 組件,以下:

image

只須要在生產服務器上啓動一個 gor 進程,它負責全部的工做包括監聽、過濾和轉發。 它的設計遵循 Unix 設計哲學:一切都是由管道組成的,各類輸入將數據複用爲輸出

輸入輸出一般被成爲插件,常見的有下面幾種。

可用輸入:

  • --input-raw 用於捕獲 HTTP 流量,您應該指定 IP 地址或接口和應用程序端口。
  • --input-file 接受流量輸出的文件(--output-file),用來離線流量重放。
  • --input-tcp 若是您決定未來自多個轉發器 Gor 實例的流量轉發給它,則由 Gor 聚合實例使用。

可用輸出:

  • --output-http 重放 HTTP 流量到給定的端點,接受基礎 URL。
  • --output-file 記錄傳入的流量到文件。更多關於保存和從文件重播
  • --output-tcp 將傳入數據轉發給另外一個 Gor 實例,並與其一塊兒使用--input-tcp。
  • --output-stdout 用於調試,輸出全部數據到 stdout。

你能夠對數據進行限速、過濾、從新,還能夠重用中間件實現一些自定義邏輯處理,如私有數據的過濾、認證等個性需求。

其餘經常使用參數:

  • --output-http "staging.com|10" 輸出流量的 10%
  • --http-allow-method 根據請求方式過濾。
  • --http-allow-url url 白名單,其餘請求將會被丟棄。
  • --http-disallow-url 趕上一個 url 相反,黑名單,其餘的請求會被捕獲到。

本文不對中間件作過多描述,僅討論經常使用功能,對中間件有需求的可參考中間件文檔

goreplay 搭建

Goreplay 是使用 golang 開發的,咱們能夠直接使用編譯好的對應各系統的二進制文件,也能夠本身編譯,咱們這裏直接使用二進制文件。

wget https://github.com/buger/goreplay/releases/download/v1.3.0_RC1/gor_1.3_RC1_x64.tar.gz
tar zxvf gor_1.3_RC1_x64.tar.gz
# 解壓出二進制文件 gor
gor
複製代碼

接下來,直接啓動 gor 便可複製流量和轉發。

sudo ./gor --input-raw :8000 --output-http="http://192.168.33.13:8001"
複製代碼

複製本地 8000 端口的流量到 http 遠端服務http://192.168.33.13:8001。(複製同端口的流量時,流量會重複。這是 gor 的一個 bug,截止目前 1.3 版本仍可復現,可見issue292)

goreplay 的流量轉發,並非直接 tcp 包的轉發,而是從新組織 http 協議級別的請求,發送到測試服務器。因此它是新的 gor 線程和測試服務器的交互,和監聽線程無關,因此無需對流量進行攔截。

包流向分析

下面咱們來看下 gor 複製的流量包的流向過程:

gor

紅色標註塊爲正常流量,藍色標註塊爲複製的流量。

看到此處,你可能會有疑問,爲何 gor 不用攔截流量?

你們仔細看 tcpcopy 和 gor 複製流量的端口,在生產機和測試機創建鏈接時,tcpcopy 雖然修改了 tcp 包的源 ip,但端口仍是用的請求客戶端的端口,是 tcp 數據鏈路層級別的流量複製。而 gor 這裏嚴格來講並非複製,而是從新構建了 http 請求。使用新端口來和測試機建連,相對的測試機在回包時,即便包是回到了生產機,但因爲是和客戶端不一樣的端口,也不會對生產流量形成影響。

對比總結

到此,咱們對流量複製有了些基本的概念和應用了,也對 tcpcopy 和 goreplay 兩款開源工具備了必定的認知。兩款開源工具各有優缺點,咱們來一塊總結下。

  • tcpcopy 部署架構相對複雜,goreplay 相對簡單隻需啓動一個進程。
  • tcpcopy 支持的協議比較豐富,goreplay 根據架構特色僅支持 http。
  • tcpcopy 和 goreplay 都支持離線和在線錄製回放。

簡單 http 複製 goreplay 徹底能夠勝任,稍複雜點或應用場景更復雜,那麼推薦 tcpcopy。更復雜,要求更高的流量複製,那隻能咱們本身定製了。

好了,本篇到這結束了,歡迎留言討論,你覺着最佳流量複製方案。

我是DeanWu,一個努力成爲真正SRE的人。

關注公衆號「碼農吳先生」, 可第一時間獲取最新文章。回覆關鍵字「go」「python」獲取我收集的學習資料,也可回覆關鍵字「小二」,加我wx拉你進技術交流羣,聊技術聊人生~

相關文章
相關標籤/搜索