新建工程
創(chuàng)建新目錄 jmeter_demo 在該目錄下打開命令行輸入:
shell
復制代碼
go mod init jmeter_demo go mod tidy
隨后創(chuàng)建各目錄與文件如下:
shell
復制代碼
-- jmeter_demo -- main main 函數目錄(啟動http和grpc服務) -- main.go -- proto grpc server 的目錄 -- chat.go -- chat.pb.gp -- chat.proto -- test_plan jmeter 測試計劃 -- test_plan.jmx go.mod
main 函數
go
復制代碼
package main import ( "google.golang.org/grpc" "io" proto "jmeter_demo/proto" "log" "net" "net/http" ) func main() { // start a grpc service lis, err := net.Listen("tcp", ":8000") if err != nil { log.Fatalf("Fail to listen: %v", err) } s := proto.Server{} grpcServer := grpc.NewServer() proto.RegisterChatServiceServer(grpcServer, &s) go func() { if err := grpcServer.Serve(lis); err != nil { log.Fatalf("Fail to serve: %v", err) } }() // start a http service http.HandleFunc("/fib1", fibHandler1) http.HandleFunc("/fib2", fibHandler2) go func() { http.ListenAndServe(":2000", nil) }() select {} } func fibHandler1(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { w.Write([]byte("method error")) return } bodyBytes, err := io.ReadAll(r.Body) if err != nil { w.Write([]byte("read body error")) return } if string(bodyBytes) == "" { w.Write([]byte("body empty")) return } fib(0) w.Write([]byte("hello from fib handler1")) } func fibHandler2(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { w.Write([]byte("method error")) return } bodyBytes, err := io.ReadAll(r.Body) if err != nil { w.Write([]byte("read body error")) return } if string(bodyBytes) == "" { w.Write([]byte("body empty")) return } fib(30) w.Write([]byte("hello from fib handler2")) } func fib(n int) int { if n < 2 { return 1 } return fib(n-1) + fib(n-2) }
main 函數非常的 簡單, 起了一個 grpc 接口 和兩個 http 接口, 兩個http 接口功能完全一致,都是運行一個斐波那契數列計算后返回一個字符串, 但兩個 handler 的返回略有不同。
grpc 服務的函數非常簡單, 直接 return 了一個字符串, 我展示出來, 就不做詳細解釋了, 具體開源參照我的另一篇博客
chat.proto
proto
復制代碼
syntax = "proto3"; package proto; option go_package="/"; // 定義 message message ChatMessage { string body = 1; } // 定義 service service ChatService { rpc SayHello(ChatMessage ) returns (ChatMessage ) {} }
chat.go
go
復制代碼
package __ import ( "fmt" "golang.org/x/net/context" ) type Server struct { } func (s *Server) SayHello(ctx context.Context, in *ChatMessage) (*ChatMessage, error) { fmt.Printf("Receive message body from client: %s \n", in.Body) return &ChatMessage{Body: "Hello From the Grpc Server!"}, nil }
Jmeter 的使用
Jmeter 環(huán)境搭建
-
Jmeter 運行依賴于的 java 環(huán)境, 所以需要你提前安裝好 java 環(huán)境。安裝好 Java 后大家可以前往官網下載Jmeter. 這篇博客的Jmeter 版本是 Jmeter 5.6.2 版本。安裝完以后,點擊安裝目錄/bin/jmeter.bat 即可啟動jmeter.
-
安裝Jmeter 插件。JMeter 默認是不支持 grpc的,需要額外安裝插件, 大家可以前往JMeter的github, 下載 jmeter-grpc-request.jar 包然后放入 jmeter安裝目錄/lib/ext下。
-
安裝繪制響應時間圖插件。大家前往 Jmeter插件網站, 下載 plugin-manager.jar 包, 然后也是放入 jmeter安裝目錄/lib/ext下.
安裝完插件以后, 你需要重啟 JMeter
JMeter 重要概念
下面這張圖是這篇博客使用到的 JMeter 的完整展示, 我將圍繞著下圖中的各個組件對JMeter如何使用進行解釋。
測試計劃 (Test Plan):
測試計劃,是 Jmter 中的工作單位,Jmeter 的測試都是以測試疾患為單位的,測試計劃可以被保存,也可以被導入。 在測試計劃中可以 自定義一些變量方便后續(xù)使用。 比如我就定義了兩個變量 fib1 和 fib2. 一打開Jmeter 就會有一個 Test plan 的測試計劃放在左上角了
線程組(Thread Group)
線程組,相當于測試計劃的流水線,壓測過程嚴格按照線程組的規(guī)定進行。比如我們可以設置發(fā)起壓測請求所調用的用戶線程數, 壓測的次數或者 壓測的時間, 遇到報錯如何處置(暫停測試還是進行下一次測試)等等。
我們在測試計劃右鍵 -> Add -> Thread(Users) -> Thread Group 即可添加線程組
事務控制(Transaction Controller)
Jmeter 的事務和 MYSQL中的 事務類似,一個事務中可以包括多個請求, 比如 我在這篇博客中有兩個請求,一次HTTP請求, 一次GRPC 請求, 只有兩個請求都正常返回, 這個事務才算正常完成。
我們在線程組 -> Add -> Logic Controller -> Transaction ontroller 即可添加 事務控制
Sampler 采樣器
所謂采樣器就是,就是對接口進行采樣, 也就是發(fā)起請求的控制器。
http 采樣器
比如下圖的中的 http 采樣器 可以通過在 線程組, 右鍵 -> sampler -> http sampler 添加
我們可以定義http方法, 請求URL,和參數進行配置。 特別的是, 我在請求地址這里用到了一個隨機函數, 可以對請求的地址進行隨機化處理, 也就是 對 fib1 和 fib2 進行 1:1 的負載均衡。 如果想要實現(xiàn)其他比例的負載均衡, 那么可以在 測試計劃設置自定義 變量的數量和比例來間接實現(xiàn)。
grpc 采樣器
grpc 采樣器 可以通過在 線程組, 右鍵 -> sampler -> grpc sampler 添加
grpc 需要指定對應的 .proto 文件路徑, 如果正確添加了路徑,那么在 Full Method 的下拉框下面是可以看到函數的可選項的。proto 的字段可以通過 json 的形式進行添加。
響應斷言(Response Assertion)
所謂響應斷言, 就是判斷響應是否正常的判斷條件。比如下圖中的判斷條件是 響應是否包含特定的字符來判斷??梢栽?sampler 下右鍵 -> listener -> Response Assertion 添加
查詢結果樹(View Result Tree)
查詢結果樹就是查看響應的詳細情況, 比如查詢 http 返回的body, header。 可以在 sampler 下右鍵 -> listener -> View Result Tree 添加
聚合報告(Summary Report)
在聚合報告中, 可以直接輸出整個事務控制下的性能指標, 包括請求次數, 響應時長, 吞吐量,傳輸數據量等關鍵指標。 可以在事務控制器下 右鍵 -> listener -> Summary Report 添加
響應時間圖(Response Time Graph)
響應時間圖可以繪制響應時間于時間的關系圖,可以自定義地設置繪圖采樣的時間區(qū)間長度, 圖片尺寸等。可以在事務控制器下 右鍵 -> listener -> Response Time Graph 添加。
點擊 Display Graph 即可繪制響應時間圖:
啟動測試
點擊下圖中右邊的掃把即可清理掉歷史數據, 點擊左邊的三角形即可開始測試
最后輸出 響應時長圖:
可以看到整個事務下的多個請求的響應時間,hello grpc 接口只是一個字符串返回,所以耗時非常短;fib http 接口由于需要計算斐波那契數列, 所以耗時更長。
踩坑經驗
JMeter 本身是一個比較成熟的壓測工具, 并無特別大的坑。 我唯一遇到的坑是頁面配置的問題。啟動 JMeter 后會開啟一個命令行, 如果遇到無法保存測試計劃, 無法啟動測試等情況, 且命令行報以下類似的錯誤:
shell
復制代碼
Uncaught Exception java.lang.NoClassDefFoundError: Could not initialize classorg.apache.jmeter.gui.FileDialoger in thread Thread[AWT-EventQueue-0,6,main]. See log file for details.
你可以嘗試以下更換語言(換成英語)或者更換頁面主題,點擊左上角的 Options -> Look and Feel.文章來源:http://www.zghlxwxcb.cn/news/detail-853189.html
作者:ChesterZhang
鏈接:https://juejin.cn/post/7338783017123102732
來源:稀土掘金
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。文章來源地址http://www.zghlxwxcb.cn/news/detail-853189.html
到了這里,關于壓力測試:使用 JMeter 進行壓力測試的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!