Thrift vs Grpc內容如下鏈接
http://blog.csdn.net/dazheng/article/details/48830511
背景:Facebook 開發的遠程服務調用框架 Apache Thrift,它采用接口描述語言定義並創建服務,支持可擴展的跨語言服務開發,所包含的代碼生成引擎可以在多種語言中創建高效的、無縫的服務,其傳輸數據采用二進制格式,相對 XML 和 JSON 體積更小,對於高並發、大數據量和多語言的環境更有優勢。
負責的搜索服務使用thrift,之前是對其http的上游服務進行壓測,從而壓到該thrift服務;后續想調研一種方式能夠直接對thrift服務進行壓測。
thrift框架的C++小程序見:http://www.cnblogs.com/zhaoxd07/p/5387215.html
調研方向:
一 Jmeter
具體邏輯與使用Jmeter進行java請求的壓測方式相似:http://www.cnblogs.com/zhaoxd07/p/4895224.html
區別在於setUp中對於協議的選擇,會對結果有較大影響
TProtocol protocol = new TCompactProtocol(transport); client = new Service.Client(protocol);
原則為:與被測代碼使用協議一致即可
二 bender
https://github.com/pinterest/bender
為Pinterest公司開發的,可以對http和thrift協議做壓測,使用go語言實現的。我試了一下挺好用的,就是go語言用不太習慣
主要難點在於main.go文件的實現,與Jmeter需要注意點一致:協議的使用
具體操作步驟如下:
1 Go環境初始化
1) 下載安裝
# 下載安裝go cd /usr/local/ 自己選擇安裝目錄和工作目錄 wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz tar -xzvf go1.8.3.linux-amd64.tar.gz
2) 配置環境變量
# 環境變量配置 vim /etc/profile 增加如下行: #go variable export GOROOT=/usr/local/go export PATH=$PATH:/usr/local/go/bin export GOPATH=/data/bender/ export GOBIN=/data/bender/bin
完成后保存 並使其生效 source /etc/profile
3) 確認變量配置是否生效
#echo $GOROOT
/usr/local/go
2 下載安裝需要的插件
cd $GOPATH
go get git.apache.org/thrift.git/lib/go/thrift go get github.com/pinterest/bender
3 准備server和client
准備server和client
因為我這是個實際項目,server已經由開發同學實現並啟動,所以此時只需要准備server即可。如下
Server
cd $GOPATH/workspace/myProject/ # 進入我的工作目錄
rz my_interface.thrift # 上傳我的接口文件
thrift -gen go my_interface.thrift # 將thrift文件轉成go語言
4 准備壓測腳本bender
編寫壓測文件 在myProject目錄下 新建 myBender文件夾,vim main.sh如下:
package main // import 若提示有錯,就看下目錄下文件是否可用 import ( "github.com/pinterest/bender" bthrift "github.com/pinterest/bender/thrift" "git.apache.org/thrift.git/lib/go/thrift" .... "github.com/pinterest/bender/hist" ) // 准備壓測數據,我用的服務的日志,解析后作為請求發送,相當於回放 func SyntheticRequests(n int) chan interface{} { f, err := os.Open("./advanced_search.info") paramList := make([]*as.QueryParam, 0) if err != nil { panic(err) } defer f.Close() rd := bufio.NewReader(f) for { line, err := rd.ReadString('\n') if err != nil || io.EOF == err { break } else { json_transport := thrift.NewTMemoryBufferLen(len([]rune(line))) json_transport.WriteString(line) json_protocol := thrift.NewTJSONProtocol(json_transport) param := as.NewQueryParam() param.Read(json_protocol) paramList = append(paramList, param) } } max := len(paramList) c := make(chan interface{}, 100) go func() { for i := 0; i < n; i++ { rand.Seed(int64(time.Now().Nanosecond())) c <- paramList[rand.Intn(max)] } close(c) }() return c } //重要:需要跟服務端所用協議一致 func ASExecutor(request interface{}, transport thrift.TTransport) (interface{}, error) { pFac := thrift.NewTCompactProtocolFactory() client := as.NewRecommendSrvClientFactory(transport, pFac) return client.GetCampaigns(request.(*as.QueryParam)) } // 主要是用bender的接口,完成壓測 func main() { intervals := bender.ExponentialIntervalGenerator(150) // 150 -- qps requests := SyntheticRequests(150*60*1) //總請求數 //buffer字節數, clientExec, 超時時間, hosts--寫server所在的ip和端口,如非同一機器,保證端口可訪問 exec := bthrift.NewThriftRequestExec(thrift.NewTBufferedTransportFactory(125), ASExecutor, 100 * time.Second, "127.0.0.1:9099") recorder := make(chan interface{}, 128) bender.LoadTestThroughput(intervals, requests, exec, recorder) l := log.New(os.Stdout, "", log.LstdFlags) h := hist.NewHistogram(60000, 1000000) bender.Record(recorder, bender.NewLoggingRecorder(l), bender.NewHistogramRecorder(h)) fmt.Println(h) }
5 運行及結果
1 編譯
cd $GOPATH
go install workspace/asthrift/asbender // main.go在目錄asbender下
編譯后的可執行文件在目錄bin下,貌似新文件不能直接覆蓋舊文件,因此我會先手動刪除舊文件
2 執行
如下結果是因為所請求的server未啟動(因該服務現階段不屬於我維護,該結果僅做參考示例)
[root@ip bin]#./asbender Percentiles: Min: 0 Median: 1 90th: 1 99th: 1 99.9th: 1 99.99th: 4 Max: 10 Stats: Average: 0.923222 Total requests: 9000 Elapsed Time (sec): 59.5483 Average QPS: 151.14 Errors: 9000 Percent errors: 100.00
6 問題與解決
使用直接下載的bender運行時,會打印出請求的詳細資料,導致壓測的qps不能完成預期,可手動注釋掉bender相關代碼,並重新編譯。
vim src/github.com/pinterest/bender/recorders.go,注釋掉第44行。
41 // NewLoggingRecorder creates a new log.Logger-based recorder. 42 func NewLoggingRecorder(l *log.Logger) Recorder { 43 return func(msg interface{}) { 44 // logMessage(l, msg) 45 } 46 }
刪除目錄下的pkg/linux_amd64/github.com/pinterest/bender.a文件,並重新編譯:
go install github.com/pinterest/bender