sniffer-agent
抓取tcp包解析出mysql語句,將查詢信息打印在屏幕上或者發(fā)送到Kafka绳军。
1. Architecture
架構(gòu)設(shè)計:
本項目采用模塊化設(shè)計删铃,主要分為四大模塊:TCP抓包模塊踏堡,協(xié)議解析模塊,輸出模塊顷蟆,心跳模塊
2. Parse Protocol
sniffer-agent采用模塊化結(jié)構(gòu)帐偎,支持用戶添加自己的解析模塊,只要實現(xiàn)了統(tǒng)一的接口即可
- MySQL
- PostgreSQL
- Redis
- Mongodb
- GRPC
詳細輸出格式查看
3. CapturePacketRate
sniffer-agent可以動態(tài)設(shè)置抓包率豁生,詳情查看文檔
4. Exporter
輸出模塊主要負(fù)責(zé)漫贞,將解析的結(jié)果對外輸出。默認(rèn)情況下輸出到命令行迅脐,可以通過指定export_type參數(shù)選擇kafka,這時候會直接將解析結(jié)果發(fā)送到kafka谴蔑。
同樣只要實現(xiàn)了export接口龟梦,用戶可以自定義自己的輸出方式计贰。
5. Install:
環(huán)境:
golang:1.12
libpcap包
測試腳本運行在python3環(huán)境下
1.安裝依賴躁倒,目前自測支持Linux系列操作系統(tǒng),其他版本的系統(tǒng)有待驗證
CentOS:
yum install libpcap-devel
Ubuntu:
apt-get install libpcap-dev
2.執(zhí)行編譯命令 go build
6. Demo
目前只支持MySQL協(xié)議的抓取挣输,需要將編譯后的二進制文件上傳到MySQL服務(wù)器上
1.最簡單的使用
./sniffer-agent
2.指定log級別,可以指定的值為debug停士、info完丽、warn、error蜻底,默認(rèn)是info
./sniffer-agent --log_level=debug
默認(rèn)會監(jiān)聽 網(wǎng)卡:eth0薄辅,端口3306
3.指定網(wǎng)卡和監(jiān)聽端口
./sniffer-agent --interface=eth0 --port=3358
4.指定輸出到kafka抠璃,為了將ddl和select、dml區(qū)分處理窿春,這里使用了兩個topic來生產(chǎn)消息
./sniffer-agent --export_type=kafka --kafka-server=$kafka_server:$kafka_server --kafka-group-id=sniffer --kafka-async-topic=non_ddl_sql_collector --kafka-sync-topic=ddl_sql_collector
5.指定嚴(yán)格模式,通過查詢獲取長連接的用戶名和數(shù)據(jù)庫
./sniffer-agent --strict_mode=true --admin_user=root --admin_passwd=123456
7. 題外話
在做這個功能之前采盒,項目組調(diào)研過類似功能的產(chǎn)品旧乞,最有名的是 mysql-sniffer 和 go-sniffer,這兩個產(chǎn)品都很優(yōu)秀磅氨,不過我們的業(yè)務(wù)場景要求更多良蛮。
我們需要將提取的SQL信息發(fā)送到kafka進行處理,之前的兩個產(chǎn)品輸出的結(jié)果需要進行一些處理然后自己發(fā)送悍赢,在QPS比較高的情況下决瞳,這些處理會消耗較多的CPU货徙;
另外mysql-sniffer使用c++開發(fā),平臺的適用性較差皮胡,后期擴展較難痴颊。
開發(fā)的過程中也借鑒了這些產(chǎn)品的思想,另外在MySQL包解析的時候屡贺,參考了一些 Vitess 和 TiDB 的內(nèi)容蠢棱,部分私有變量和函數(shù)直接復(fù)制使用,這里向這些優(yōu)秀的產(chǎn)品致敬甩栈,如有侵權(quán)請隨時聯(lián)系玉转。
8. 結(jié)果分析
在壓測的過程中和mysql-sniffer進行了結(jié)果對比究抓,壓測執(zhí)行28萬條語句,mysql-sniffer抓取了8千條橘茉,sniffer-agent抓取了30萬條語句(其中包含client自動生成的語句)
9. 風(fēng)險提示
1.sniffer-agent使用了pacp抓包捺癞,根據(jù)pacp抓包原理,在IO較高的時候有一定的概率丟包唐础;
2.sniffer-agent提供了Prepare語句的支持一膨,但是如果sniffer-agent在prepare語句初始化之后啟動,就無法抓取prepare語句瞒津;