前言
Jmeter是一款性能測試,壓力測試的開源工具,被大量的測試人員拿來測試產品的性能,負載等等。 Jmeter除了強大的預置的各種插件,各種可視化圖表工具以外,也有些固有的缺陷,例如:
- 我們往往只能在報告中分析同一個部署的性能,不方便進行縱向的比較,例如我們每個build都會跑一次性能測試,但是兩個build之間性能有沒有變差?這些只能我們拿到結果報告,然后自己用其他第三方工具來分析
- Jmeter的圖表插件產生的報告不夠靈活,一般是固定的幾個維度,不能更靈活的進行分析
本文會嘗試將JMeter的sample數據寫入ElasticSearch,然后通過Kibana強大的搜索和可視化能力,進行各種維度的性能分析,幫助開發測試人員找出性能的瓶頸,監控系統性能的變化情況,給整個開發,測試和運維團隊發布各種報告
問題
如何自動化的把性能測試的各種原始數據寫入ElasticSearch
信息采集上這里有兩種可行的方案,
- 一種讓JMeter生成各種報告,然后在測試跑完之后,用自己寫的結果分析腳本,把數據導入ElasticSearch,這種方式不影響JMeter的運行,但是不具有通用性/實時性,而且由於一般JMeter的各種報告並沒有包含全面的性能信息,這些信息的缺失是致命的,沒有原始信息,接下來的各種分析就是無源之水
- 另外一種,就是我們采用的,實時的采集JMeter的Sample的性能信息,在不影響JMeter本省性能的情況下,相對實時的把結果寫入ElasticSearch。優點是信息比較完備,而且可以包含其他自定義參數,在跑長時間的負載測試的時候,可以實時的監控系統的性能
對於數據采集,技術上,我們采用了開發一個JMeter的Backend Listener插件,這個插件會處理JMeter的每個Sample的結果
與BackendListener有關的信息可以查看 http://jmeter.apache.org/api/org/apache/jmeter/visualizers/backend/BackendListenerClient.html
我們着重看看SampleResult包含的信息,基本上我們可以拿到:
- 請求的URL
- 請求的各種參數
- Cookies
- Headers
- Paramters
- 響應的各種參數
- Headers
- Cookies
- Body
- Response Code
- JMeter相關信息
- Sample Label
這些信息已經足夠我們用來分析性能了,在具體采集上,我們也會看自己的需要,只保存感興趣的參數,用來節省ElasticSearch的存儲空間,例如只保存出錯的響應的body
關於SampleResult,具體可以參見 https://jmeter.apache.org/api/org/apache/jmeter/samplers/SampleResult.html
對於保存采樣結果,技術上也有幾個選擇:
- 通過ElasticSearch的RestClient
- 通過我們這里使用的TransportClient
- 通過ElasticSearch的NodeClient
三種方式性能是依次提高的,能實現的功能也是逐個增強的。因為我們只是保存數據,並沒有ElasticSearch的管理的需求,但是對性能有很強的需求,所以我們選擇了TransportClient, 關於三種連接方式的具體介紹,可以參見:
- RestClient https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html
- TransportClient https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html
- NodeClient https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/client.html
如何不影響JMeter本身的性能
JMeter本身就需要生成和管理多個Threads,所以一般情況下,並不建議JMeter 的Test Plan中,包含圖形化的分析插件,或者盡量減少各種分析插件的使用。我們引入一個Backendlistener,當然也不希望影響JMeter的性能,或者盡量減少對JMeter本身的影響,我們的策略是:
采用異步的策略,每50個采樣的結果,通過ElasticSearch bulk ingest的API,存入ElasticSearch,減少網絡的開銷。當然,這里的50是可以自己配置的,根據自己的機器性能、采樣數據的大小和網絡狀況確定
可以定制化的數據保存策略,例如只保存感興趣的采樣信息
而JMeter本身的BackendListener也是異步的,JMeter的Load並不會等待結果的存儲是否完成
當然,具體的性能影響,也需要嚴格的測試確定,這里我就不展開了,可能接下來會進行一些相關的測試
如何支持Jmeter的Controller/Server的部署方式
初步看下來,JMeter是把各個Server的Sample信息傳給Controller處理的,所以呢,當JMeter部署規模比較大的時候,Controller的Sample信息處理會重一些,好在我們一般情況下,Controller上並不會有Load需要處理,所以也還好。。。但是對於插件的使用上,我接下來會部署幾台JMeter的server確認下,是各個Server來處理SampleResult還是傳回Controller,這個我會在更新中詳細介紹,公司的網絡,各種限制,還沒有機會做這部分。
如何保存各種自定義的參數(除了Jmeter自己提供的參數之外),用於為將來提供更多分析的可能性
比如我們希望保存當前部署的產品的版本號,這個在比較各個不同版本的性能的時候,非常有用。我們在插件中,會把當前機器的以自定義的字符串開頭的環境變量都存儲到每條JMeter的記錄中去。事后,用戶就可以很靈活的使用這些自定義的參數來分析性能了(例如,地域代碼,產品部署相關的各種參數)
由於時間的問題,今天先介紹下大概的情況,接下來我會更新
- 如何創建一個JMeter BackendListener,並且調用ElasticSearch的TransportClient保存SampleResult
- 如何使用Kibana/Kibana Timelion從各個維度分析性能結果
- 如何與Jenkins集成,創建完成一套性能測試的框架,讓所有者一切對使用者都透明
接下來我會把相關的Code放到Github上,並把相關代碼開源, 請關注后續的更新。