當 ElasticSearch 的業務量足夠大,比如每天都會產生數百 GB 資料的時候,你就會自然而然的需要一個效能更強的 ElasticSearch 叢集。特別是當你使用的場景是一些典型的大量資料進入的場景,比如網站日誌、使用者行為記錄、大型電商網站的站內搜尋時,一個強勁的 ElasticSearch 是必不可少的元件。在這樣的場景下,如何找到一組合適的 ElasticSearch 叢集?如何評估 ElasticSearch 叢集的效能,就成為了一個十分重要的因素。
用什麼 ElasticSearch 進行壓力測試?
對於 ElasticSearch 效能測試和壓力測試方面,其實有很多不同的方案,比如:
- Rally:Rally 是 Elastic 官方針對於 ElasticSearch 的巨集觀測試工具。
- ESPerf:一個基於 Golang 編寫的 ElasticSerch 效能測試工具
- Elasticsearch Stress Test:由著名的 ElasticSearch 服務提供商 Logzio 開發的效能測試工具
除了這些定製化的工具意外以外,ElasticSearch 也可以藉由其 Restful API 來使用Load Runner、JMeter等老牌工具進行測試,這些工具零零散散,各有各的用法和用途,不過,對於廣大開發者而言,還是官方出的 Rally 更令人滿意。
在本篇文章中,將會使用 Rally 來完成 ElasticSearch 叢集的壓力測試
Rally 作為官方出品的工具,來自官方的信任加成讓他成為各家進行壓力測試的首選工具。其次, Rally 官方給出了多種預設的資料集(Tracks)。如果你的使用場景覆蓋在這些資料集(比如HTTP 訪問事件資料、地理名稱資料、地理座標點資料、HTTP 請求日誌、問答場景、叫車記錄等場景)中,可以直接使用已有的資料集,來完成測試,而無需製造測試資料。
即使你的場景比較特殊,無法被官方的資料集所覆蓋,也依然可以根據自己的線上資料,來建立資料集,確保測試效果的準確。
如何使用 Rally 進行測試?
在瞭解了 Rally 後,來具體看一看 Rally 的使用。
測試前的準備
關於 Rally 的基本安裝,這裡就不再介紹,總的來說十分簡單,在配置好了 JDK 和 Python 環境以後,只需要執行pip install rally
就可以完成安裝。如果你的環境複雜,希望以一個更簡單的方式來執行,你也可以選擇使用 Docker 來執行 Rally ,進行測試。關於更多的安裝方式,你可以參考 Rally 的安裝文件.
在安裝完成了 Rally 後,就可以開始進行 ElasticSearch 的測試。
在測試前,你需要先了解一些基本概念
- race:在 Rally 中,每一次測試都可以稱之為 race
- car: 在 Rally 中,每一個參與測試的叢集,都可以稱之為 car ,不同的叢集就是不同的 car,如果你是在選配置,則可以通過切換 car 來設定不同配置的測試。
- track: 在 Rally 中,每一次測試用的資料,都可以稱之為 Track,不同的 Track 意味著不同的測試資料。
- challange: 在 Rally 中,每一個 challange 意味著一個不同的測試場景,具體的場景則代表著 ElasticSearch 所執行的操作。
在瞭解測試的基本概念後,就可以開始進行壓力測試。
進行壓力測試
測試裝置
由於本次測試實際上是一次選型的過程,在測試之前,我曾閱讀了 Elastic 官方的權威指南中的硬體部分.在其文件中提供了對於運轉 ElasticSearch 叢集裝置的推薦配置。
- 64 GB 記憶體的機器是非常理想的, 但是32 GB 和16 GB 機器也是很常見的。少於8 GB 會適得其反(你最終需要很多很多的小機器),大於64 GB 的機器也會有問題, 我們將在 堆記憶體:大小和交換 中討論。
- 如果你要在更快的 CPUs 和更多的核心之間選擇,選擇更多的核心更好。多個核心提供的額外併發遠勝過稍微快一點點的時脈頻率。
- 如果你負擔得起 SSD,它將遠遠超出任何旋轉介質(注:機械硬碟,磁帶等)。 基於 SSD 的節點,查詢和索引效能都有提升。如果你負擔得起,SSD 是一個好的選擇。
- 通常,選擇中配或者高配機器更好。避免使用低配機器, 因為你不會希望去管理擁有上千個節點的叢集,而且在這些低配機器上執行 Elasticsearch 的開銷也是顯著的。
因此,我選擇了原本打算購買的三家廠商(阿里雲、騰訊雲、UCloud)的裝置進行測試,在具體的配置層面,則在各家購買四臺 8C64G 100GBSSD磁碟的的雲主機來進行測試。
測試環節
1. 構建叢集
在進行測試前,需要先對已有的三臺裝置搭建叢集,並配置叢集連結,確保叢集正常工作。叢集搭建的部分,你可以參考官方文件中的Add and remove nodes in your cluster部分。
2. 執行測試命令
在完成了叢集的建設後,測試就簡單很多,只需要執行命令,便可以對已經建設好的叢集進行測試,比如:
esrally --track=pmc --target-hosts=10.5.5.10:9200,10.5.5.11:9200,10.5.5.12:9200 --pipeline=benchmark-only
執行完命令後,接下來就是漫長的等待,根據機器的配置和叢集等
3. 獲得測試結果
在執行了測試命令後,測試完成後,你就可以獲得相應的測試結果。不過,為了方便進行對比和檢視,你可以在測試的命令中加入引數,從而實現將測試結果匯出為特定的格式。
比如,執行這樣的測試命令,就可以獲得 CSV 格式的測試資料
esrally --track=pmc --target-hosts=10.5.5.10:9200,10.5.5.11:9200,10.5.5.12:9200 --pipeline=benchmark-only -report-format=csv --report-file=~/benchmarks/result.csv
當你得到了 csv 的結果後,就可以對資料進行分析和對比了。
如何檢視 Rally 的測試結果
當我們對 Rally 執行測試以後,我們會拿到大量的資料,而具體這些資料應該如何來看呢?接下來我們一一來看。
如何理解 Rally 的資料
Rally 匯出的資料共有 4 列,分別是 Metric(維度)、Task(任務)、Unit(單位)和Result(結果)。
我們可以將資料按照 Task 進行切分,你可以得到若干組結果,如:
- 沒有 Task 的巨集觀資料
- index-append 組資料
- index-stats 組資料
- node-stats 組資料
- phrase 組資料
- ...
不同的組意味著 ElasticSearch 在不同場景下的應用,因此,你在對比時,需要按照分組來看資料。而分組內部的資料,就簡單了許多,除了巨集觀資料以外,其他各組的資料基本上都是一個模式的,具體可以分為以下 14 組資料。
- Min/Median/Max:本組測試的最小吞吐率、中位吞吐率和最大吞吐率,單位為 ops/s ,越大越好。
- 50th/90th/99th/100th percentile latency: 提交請求和收到完整回覆之間的時間段,越小越好
- 50th/90th/99th/99.9th/100th percentile service time:請求處理開始和接收完整響應之間的時間段,越小越好
- error rate:錯誤率,錯誤響應相對於響應總數的比例。任何被 Elasticsearch Python 客戶端丟擲的異常都被認為是錯誤響應(例如,HTTP 響應碼 4xx、5xx或者網路錯誤,如網路不可達)。
當你能夠理解資料的劃分方式後,對於 Rally 返回的眾多資料就比較好理解了。接下來,我們以實際例子來看 Rally 返回的資料。
如何理解 Rally 返回的巨集觀測試資料
這裡以我測試的資料為例。
根據每組資料對應的不同操作,我們可以將其資料分為若干組,這裡我將資料按照顏色進行了一個基礎的劃分,從上到下依次為:
- 索引時間
- 索引節流時間
- 合併時間
- 合併節流時間
- 重新整理時間
- 重刷時間
首先,先看第一組的索引時間,索引時間共有四個指標:
- Cumulative indexing time of primary shards: 主分片累計索引時間
- Cumulative indexing time across primary shards:跨分片累計索引時間
- Cumulative indexing throttle time of primary shards:主分片累計節流索引時間
- Cumulative indexing throttle time across primary shards:跨分片累計節流索引時間
這四個指標說明了 ElasticSearch 在進行資料處理所需要的索引時間,因此,時間越短越好。
Metric | 騰訊雲 | UCloud | 阿里雲 |
---|---|---|---|
Cumulative indexing time of primary shards | 25.262833333333300 | 19.2662 | 21.40011666666670 |
Min cumulative indexing time across primary shards | 5.0297 | 3.8177666666666700 | 4.2537666666666700 |
Median cumulative indexing time across primary shards | 5.052066666666670 | 3.8252333333333300 | 4.272083333333330 |
Max cumulative indexing time across primary shards | 5.076316666666670 | 3.9190666666666700 | 4.3139 |
在本組測試結果中,騰訊雲的計算時間耗費最長,阿里雲可以在騰訊的基礎之上,有約 16 % 的效能提升,UCloud 則在騰訊雲的基礎之上提升了 24%。
在測試過程中,會因為機器的效能等因素,而造成實際測試時間的不同。在這三組中,阿里雲是最神奇的一個,因為它測試時間達到了6個小時。而 UCloud 和騰訊雲則分別在 3 小時和 4 小時左右,實際的測試體驗還是有很大的差距。如果你要復現相應的實驗,建議你在早上進行,這樣出測試結果的時候剛好還在白天。
接下來看合併時間的資料
- Cumulative merge throttle time of primary shards:主分片累計節流合併時間
- Min cumulative merge throttle time across primary shards:主分片累計節流合併時間
- Median cumulative merge throttle time across primary shards:主分片累計節流中位合併時間
- Max cumulative merge throttle time across primary shards:主分片累計節流最大合併時間
合併時間組結果類似於索引時間組,不同的是測量的資料 Merge 時間。和 index 類似,時間越短越好,合併數量越大越好。
Metric | 騰訊雲 | UCloud | 阿里雲 | Unit |
---|---|---|---|---|
Cumulative merge time of primary shards | 12.6379 | 7.717366666666670 | 11.083600000000000 | min |
Cumulative merge count of primary shards | 90 | 116 | 99 | |
Min cumulative merge time across primary shards | 2.2037 | 1.43605 | 1.8695333333333300 | min |
Median cumulative merge time across primary shards | 2.5391166666666700 | 1.5713166666666700 | 2.2406333333333300 | min |
Max cumulative merge time across primary shards | 2.733966666666670 | 1.6538166666666700 | 2.5342 | min |
在本組測試結果中,騰訊雲的計算時間耗費最長,阿里雲可以在騰訊的基礎之上,有約 9 % 的效能提升,UCloud 則在騰訊雲的基礎之上提升了 30%~40%
其他幾組類似的資料,這裡就不再一一介紹,大家可以自行下載文章最後的資料進行分析,評估,得出結論。
如何理解 Rally 返回的專案測試資料
除了巨集觀資料以外,Rally 返回資料中極大比例的是各種不同場景下的資料,這裡,我們也選兩組資料進行對比分析,看一看這些資料應該如何理解。
首先,我們看一下 node-stats 組的結果。
node-stats 組的結果是針對 node-stats 命令的資料分析結果。這裡的吞吐量越大越好,時延則越小越好。
Metric | Task | 騰訊雲 | UCloud | 阿里雲 | Unit |
---|---|---|---|---|---|
Min Throughput | node-stats | 90.07 | 90.07 | 90.07 | ops/s |
Median Throughput | node-stats | 90.11 | 90.11 | 90.12 | ops/s |
Max Throughput | node-stats | 90.39 | 90.44 | 90.42 | ops/s |
50th percentile latency | node-stats | 2.1798378893436200 | 1.491405833803580 | 1.8348334997426700 | ms |
90th percentile latency | node-stats | 2.521278689346220 | 1.8698435997976000 | 1.9605179221798600 | ms |
99th percentile latency | node-stats | 3.795880397665310 | 3.173550112005610 | 2.901402467268780 | ms |
99.9th percentile latency | node-stats | 12.884928510055500 | 9.625145497986580 | 17.55732728102550 | ms |
100th percentile latency | node-stats | 18.134295778509100 | 10.29519444455220 | 20.23470633321270 | ms |
50th percentile service time | node-stats | 2.111824500389050 | 1.4231965001272300 | 1.7749374997038100 | ms |
90th percentile service time | node-stats | 2.453031599361570 | 1.7979749004553000 | 1.8996412000888100 | ms |
99th percentile service time | node-stats | 3.686133219835030 | 2.9536031294901500 | 2.8262974901645100 | ms |
99.9th percentile service time | node-stats | 12.818092870313500 | 9.55140776220657 | 8.42020982098726 | ms |
100th percentile service time | node-stats | 16.345433999958900 | 10.22649399965300 | 20.173265999801500 | ms |
在本組測試結果中,阿里雲、騰訊雲、UCloud 在效能方面沒有較大的差距。
類似的,我們可以對比 country_agg_uncached 組的結果
Metric | Task | 騰訊雲 | UCloud | 阿里雲 | Unit |
---|---|---|---|---|---|
Min Throughput | country_agg_uncached | 3.60 | 3.61 | 3.60 | ops/s |
Median Throughput | country_agg_uncached | 3.60 | 3.61 | 3.60 | ops/s |
Max Throughput | country_agg_uncached | 3.60 | 3.61 | 3.61 | ops/s |
50th percentile latency | country_agg_uncached | 259.7333187786720 | 116.19688144446600 | 197.52657255594400 | ms |
90th percentile latency | country_agg_uncached | 264.3554400450740 | 125.7470980999640 | 201.85445903407500 | ms |
99th percentile latency | country_agg_uncached | 270.25939978284400 | 132.88548155585000 | 205.84624599263400 | ms |
100th percentile latency | country_agg_uncached | 278.76161922358700 | 133.7250455553660 | 206.57134322209500 | ms |
50th percentile service time | country_agg_uncached | 259.5503135007680 | 115.99637649987900 | 197.4296050002520 | ms |
90th percentile service time | country_agg_uncached | 264.2378849999660 | 125.53214089985000 | 201.7642059001450 | ms |
99th percentile service time | country_agg_uncached | 270.08045803115200 | 132.6980350402570 | 205.7533532799970 | ms |
100th percentile service time | country_agg_uncached | 278.6570290008970 | 133.52231299995800 | 206.47192300020800 | ms |
error rate | country_agg_uncached | 0.00 | 0.00 | 0.00 | % |
在本組測試結果中,阿里雲、騰訊雲、UCloud 在吞吐量方面沒有較大的差距,時延方面 UCloud 會更好一點。
關於更多的資料,我們不在這裡一一介紹,我將測試資料已經附在了文章的最後,你可以通過下載資料,自行分析,來練習 Rally 的使用和資料分析。
一些使用 Rally 時的小技巧
如何解決 Rally 網路不好的問題?
Rally 在執行時,需要下載相應的資料進行真實場景下的模擬,在這種情況下,Rally 需要從 AWS S3 上下載一些資料包,用於本地的測試。但國內的裝置對於 S3 的訪問不算太友好,經常會在下載的時候出現問題,因此,你可以選擇前置下載資料,這樣在測試的時候可以直接使用本地的資料來完成測試,減少失敗的可能。
想要前置下載資料也很簡單隻需要執行如下命令:
curl -O https://raw.githubusercontent.com/elastic/rally-tracks/master/download.sh
chmod u+x download.sh
./download.sh geonames
cd ~
tar -xf rally-track-data-geonames.tar
在執行 download.sh 時加入 track 名,就可以下載對應 track 資料的壓縮包到本地,你可以根據自己的實際使用情況,來決定使用什麼樣的 track 模擬真實場景。
總結
在業務真正使用 ElasticSearch 之前,你可以像我一樣,藉助於 Rally 對備選的 ElasticSearch 叢集進行壓力測試,並通過對壓測結果進行分析,從而獲得明確的選型建議。比如,在我這次測試中,顯然 UCloud 優於其他兩家,是一個價效比 更高的選擇。當然,這是一個實驗環境下的壓測,還是需要根據具體的業務場景做測試來進行選型,更為科學,不過希望壓測方法能給予大家參考,也歡迎大家在後續實際的測試過程中給予我反饋。
附錄
本文涉及到的測試資料均可以在下載地址找到。