顯示具有 JMeter 標籤的文章。 顯示所有文章
顯示具有 JMeter 標籤的文章。 顯示所有文章

2022年2月20日 星期日

JMeter 自訂輸出結果

JMeter 預設的套件能夠根據測試對象輸出像是 throughput、latency、status code 等數據的報告,不過如果遇到自己想輸出的東西是從 API response 裡萃取出來的狀況,就會稍微麻煩一點。實際上還是能夠做到,但看起來會存在一些限制,這篇會簡單紀錄一下需要做的事情。

使用 sample variables 自訂變數

JMeter 有個 sample_variables 的參數,在啟動測試時可以一起帶進去指定,JMeter 在最後輸出 JTL 時就會一起把 sample_variables 裡指定的變數一起輸出到 JTL 裡。

jmeter -Jsample_variables=price -n -t mytest.jmx -l test_result.csv

以上述的指令來說,指定的自訂變數就是 price 這個變數,只要在測試過程當中有把結果寫入到 price 變數,JMeter 在寫入 JTL 時就會把 price 一起寫進去了。輸出的結果會類似這樣:

timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect,"price"
1645111313217,1292,Random Commerce Request,200,OK,Thread Group 1-6,text,true,,946,150,10,10,https://random-data-api.com/api/commerce/random_commerce,1285,0,1010,65.85

可以看到最後面多了一個 “price” 的欄位。

產生自訂變數的報告

這個看起來存在一些限制,本來我希望的結果是產生像是 aggregate report 那樣的表格,可以幫我計算自訂變數的平均數、標準差、中位數、百分位數等等的。但目前看起來好像只能夠讓 JMeter 在產生 HTML 報告的時候引入自訂變數而已,而且報告產生的樣式似乎也沒什麼可調整的空間?不知道有沒有其他 plugin 可以協助,不過目前是沒有找到…。

這裡單純紀錄一下,產生報告的時候目前不能用 Java 17,會噴出錯誤訊息。可以換成 Java 8 或 11。

參考資料
  1. sample_variables property

2021年3月30日 星期二

JMeter 的 QPS 上不去

紀錄一下最近用 JMeter 做效能測試時遇到的小問題。

之前本來在測試效能時,因為會在測試環境進行,測試環境一般規模會比較小,所以相對地效能測試時打的流量也會比較少,大概都是打個 100~200 QPS 而已。不過這次遇到比較不一樣的狀況,我們需要在線上環境做測試,而且流量想要打高一點,結果就遇到 QPS 沒辦法往上拉的問題。

首先,測試的 script 裡設定的 Thread Group 是 1,000 個 thread,並且會用 Throughput Shaping Timer 來調整實際打出去的流量。script 跑在 AWS 上,使用的 VM 規格是 m5a.2xlarge。在 QPS ~300 左右時都還沒什麼問題,不過一往上拉到 350 QPS 以上時,就會開始出現 JMeter 顯示 response time 大幅地增加,但從 API 端觀察則看不出存在門檻,而且實際上我們日常的流量超過 350 QPS 很多…。

由於這個反應不太合理,畢竟我們平常實際運行的流量都高於 350 QPS,沒道理跑 350 QPS 的測試會卡住,更何況從 API monitoring 那邊觀察起來,API 的 response time 也很正常,並沒有如 JMeter 顯示的突然上升超過 20 倍,因此這時就開始懷疑有可能問題是出在 JMeter 這邊,像是來不及處理 response 之類的問題了。

接連做了幾個實驗、並且同時觀察 CPU 使用率後,發現一旦 QPS 超過 350 時,CPU 使用率會停留在大約 70% 左右的位置,這時多半 response time 會開始顯著地上升。因此初步認為有可能是 CPU 造成效能卡住了,而結果也確實是如此。在我把 VM 規格改為 CPU-intensive 的 c5a.2xlarge 之後,問題解決了,QPS 可以繼續往上增加,撞到了下一個門檻是大概 QPS 550…。

QPS 550 的這個門檻,觀察 CPU 使用率約莫是落在 50%~60%,看起來不太像是問題所在,因此又開始朝別的方向思考。CPU 不對的話,下一個可能就是記憶體了。此時觀察 top 顯示的整體記憶體使用率只有 2GB 出頭,但我的 c5a.2xlarge 應該有 16GB 可以使用才對,同時查到 JMeter 文件顯示預設的 heap size 是 1GB….。嗯~那就來調整 heap size 看看吧。

在 JMeter 資料夾中的 bin/jmeter 檔案裡,搜尋 HEAP 可以找到下面這一段描述:

# This is the base heap size -- you may increase or decrease it to fit your
# system's memory availability:
: "${HEAP:="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"}"

這裡顯示預設的 -Xms 和 -Xmx 都是 1GB,把它調大成想要的樣子,例如最少 8GB、最多 15GB,如下所示:

# This is the base heap size -- you may increase or decrease it to fit your
# system's memory availability:
: "${HEAP:="-Xms8g -Xmx15g -XX:MaxMetaspaceSize=256m"}"

然後~門檻就消失了,後續就順利地繼續把 QPS 往上拉到 1K 以上了。

2020年12月4日 星期五

在 JMeter 做 Mutual TLS 認證

最近要跑壓力測試時,拿之前的腳本來改,結果改完後拋出 javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_required 的錯誤訊息,研究了一段時間,才發現應該是 mTLS 方面的問題…。

在手上已經有 key、certificate 以及 CA certificate 三個 PEM 檔案的情況下,如果是用 curl 的話,指令會長的像這樣:

curl --key key.pem --cert cert.pem --cacert cacert.pem $URL

不過在 JMeter 上,則有兩種作法。一種是如果 JMeter 有打開 GUI 的話,可以從 Options → SSL Manager 來指定。不過開 GUI 一般都只會用在還在寫 script 的階段,寫完正式要跑的時候,通常還是得用 CLI 模式,因此這時需要另外一種方法,也就是自己實際產生 Client Certificate 的 keystore 檔。

Keystore for Client Certificate

要產生 Client Certificate,需要用的工具就是 keytool,指令如下:

sudo openssl pkcs12 -export -name {name} -inkey {keyPath} -in {certPath} -out {keystorePath} -password {password} -noiter -nomaciter

其中各個參數的意義如下:

  • {name}:這應該是 key 的名字吧,在我們公司的狀況,這好像是必填,但在一般狀況似乎是可以不用給這個參數。
  • {keyPath}:key 的路徑。
  • {certPath}:certificate 的路徑。
  • {keystorePath}:要產生的 keystore 要放在哪裡。
  • {password}:keystore 的密碼。這裡有特殊的格式,如果是要直接在指令上指定,則格式必須是 pass:xxxx 這樣,例如如果密碼要設定為 12345,則要給 pass:1234。但由於這樣會讓 password 可能出現在機器上(像是 ps 可能會被看到),因此如果環境不是很安全的話,建議使用 stdin 這個值來手動輸入。

執行後,keystore 就會出現在指定的位置了。

啟動 JMeter

有了 keystore 後,因為 truststore 其實本來也有了(就是 CA certificate 那個 pem 檔),因此接著只需要在啟動 JMeter 時,讓它去吃那兩個檔就好了。其中如果你的 server 的 CA 本來就是公有的 CA,那可以不用自行指定 trustStore。

/bin/jmeter.sh \
  -D javax.net.ssl.keyStore={keyStorePath} \
  -D javax.net.ssl.keyStorePasswor={keyStorePassword} \
  -D javax.net.ssl.trustStore={trustStorePath} \
  -D javax.net.ssl.trustStorePassword={trustStorePassword}
其他相關資訊
  1. JMeter 腳本裡使用的 HttpClient 實作,按照 JMeter 官方文件 [3] 的講法,是必須要用 HttpClient,否則會無法支援 KeyStore 的 Client Certification。
  2. 如果遇到的錯誤訊息是 javax.net.ssl.sslexception: closing inbound before receiving peer's close_notify 的話,原因好像有可能是 server 和 client 支援的 protocol 對不起來之類的?總之此時如果你的 JMeter 環境是跑在 Java 11 上,可以試著退回 Java 8。
  3. 不想每次執行 JMeter 時都要指定 keyStore/trustStore 的話,也可以直接把它寫在 JMeter 的 /bin/system.properties 裡。
參考資料
  1. How to Set Your JMeter Load Test to Use Client Side Certificates
  2. Mutual authentication in JMeter
  3. JMeter – Component Reference – HTTP Request
  4. Spring Boot: Jdbc javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify
  5. SSLException closing inbound before receiving peer's close_notify

2015年11月30日 星期一

在 JMeter 中驗證 JSON

在使用 JMeter 做自動化測試時,想要用比較簡單的方式處理網站回覆的 JSON
簡單查了點資料後,看起來預設的方法應該是用 JSR223 Post Processor 或者 BSF Post Processor
不過從 [1] 的描述看來,這個作法因為要把回應轉成 JavaScript 語法,實際跑起來效率頗低
如果遇到要執行的 concurrent thread 很多時,可能會把 CPU 吃滿。