[效能調教] 使用 JMeter 作為網站效能參考指標

效能調教首先就是需要一個近乎真實狀態的可重現情境來做為衡量依據,本文透過 JMeter 靈活的腳本設計方式來針對單個負載測試情境進行介紹。

前言


伴隨著系統開發到一定的段落,有關效能問題漸漸的會浮出檯面備受關注,此時如何建立合理的負載測試情境,就是與客戶角力的重點。作為客戶端當然希望要求同一秒鐘可以處理的交易數量越高越好,而作為開發端則需引導客戶關注測試情境的合理性,舉例來說若針對搶票系統,就需要針對短時間大量湧入的用戶進行瞬間高壓的負載情境測試;但若只是提供資訊的功能性網站,使用習慣必然與搶票系統截然不同,當然負載測試情境可能就會趨向穩定長時間成長的大量用戶同時在站台活動的行為來進行測試。

說了這麼多就是要先建立一些基本的概念想法,而本篇將專注在如何使用 JMeter 來協助開發人員建立相似的操作行為,並且透過參數調整來模擬大量用戶操作系統的密集性,進而達到負載測試之目的;同時藉此讓開發人員了解系統效能瓶頸及缺陷,並且可驗證改善方案執行後是否產生正向回饋。

 

介紹


JMeter 是由 Java 開發的開源軟體,也就是佛心免費讓你使用的網站效能測試軟體,可以直接到 官方網站 進行下載。由於是使用 Java 開發的應用程式,因此執行環境需要具備 Java ,啟動方式就直接執行 bin\jmeter.bat 檔案即可,開啟 JMeter 應用程式畫面如下。

 

測試情境


客戶希望系統能在 120 秒內消化 500 個用戶湧入系統執行登入行為,並且在 500 個用戶陸續登入系統的同時,已登入系統的用戶需要不定期的操作系統的特定功能 A 與 B,預期目標為所有用戶均可在 1 秒內完成登入且看到首頁的所有資訊。

分析一下需要建立的負載測試情境如下:

  1. 500 個用戶須在 120 秒內觸發登入行為完畢 (每個用戶只執行一次)
  2. 登入後需要取得首頁所有資訊 (每個用戶只執行一次)
  3. 看到頁面資訊後須隨機執行 A / B 功能 (每個用戶每隔 15 秒執行一次,持續至所有用戶登入完畢)

目標就是步驟 1 與 2 執行時間不超過  1 秒鐘就達標了!

 

建立虛擬用戶


第一步就是先建立執行續群組,以此模擬同時間一起執行特定行為的各個虛擬用戶們。

符合 500 個用戶須在 120 秒內觸發登入行為完畢的情境設定如下:

  1. 設定有意義名稱
  2. 表示 500 個虛擬用戶
  3. 表示 500 個虛擬用戶會陸續在 120 秒中均勻地啟動,執行後續設定的各測試情境
  4. 只觸發一次此群組內的所有測試情境 (登入行為)

 

準備帳密


設定好虛擬用戶後,接著就是要執行登入要模擬 500 用戶登入,首先必須要具有 500 筆帳號密碼進行模擬,針對這個需求可以先建立 blogUser.csv 檔案來存放測試用戶的帳號及密碼清單。

接著新增 CSV 資料設定功能來載入 blogUser.csv 檔案中的所有帳號密碼。

載入變數提供後續測試使用,設定方式如下:

  1. 檔案實體路徑
  2. 依序給予變數名稱 (以此名稱作為後續測試使用的變數)
  3. 忽略過第一筆資料 (因為 blogUser.csv 第一列為標題)

 

建立 HTTP 要求 - 登入


建立 HTTP 要求 取樣功能來執行登入行為。

接著依據登入網站的 Web API 規格進行以下設定:

  1. 給定主機位置 (如果大家都一樣可以考慮新增 HTTP 要求預設值 統一設置此參數)
  2. 給定 HTTP 要求的方法及路徑
  3. 給定 POST 到伺服器的資料,其中 ${id}${pwd} 是從 blogUser.csv 取出的帳密資料。

接著在此 HTTP 要求 中建立HTTP 標頭管理員 來設置 HTTP 標頭。

設定 content type 為 json 格式。

 

執行測試


執行測試的方式除了點選上方工具列外,最快的方式就是使用快捷鍵 Ctrl + E (清除統計資料) 及 Ctrl + R (開始測試) 來執行測試;由於只是要先測試情境是否設定正確,因此先調整執行續為 1 來執行單次驗證。我們可以透過新增 Summary Resport 檢視結果樹 兩個功能來觀看執行的結果,確認功能都無誤後再建立接續的情境。

執行測試後,在檢視結果樹中可以看到每一筆 HTTP 要求的細部資料:

  1. 每次 HTTP 要求清單
  2. POST 資料確實取自 blogUser.csv 檔案中的帳號密碼 
  3. 正確套用我們所設定的 HTTP 標頭
  4. 在實際大量測試時,可設定【只記錄錯誤】模式,僅保留錯誤的 HTTP 要求供查驗

 

Summary Report中可以看到各 HTTP 要求的回應時間統計資訊 (時間單位為毫秒)。

 

取得成功登入後回傳的 token 值


登入情境完成後,接著需建立取得首頁資訊的相關 HTTP 要求,但是該些資訊都是受到保護的,也就表示需要藉由登入後回傳的 token 作為令牌才能夠合法訪問 Web API 取得資訊,因此我們必須完成以下兩件事情。

  1. 解析登入後回傳的資料,取得合法 token 值
  2. 傳遞 token 至接續的測試情境,確保訪問 Web API 的合法性

 

首先需分析登入後回傳的 JSON 資料格式,其中可發現 token 值位於陣列中第一個物件的 Token 屬性中。

接著在登入系統 HTTP 要求下新增 JSON Extractor 項目,以此工具從回傳資料中擷取出 Token 值。

擷取 JSON 資料中的 token 設定值如下:

  1. 擷取出的數值會以 tkn 變數存在於接續的測試情境中
  2. 使用 $[0].Token 表示擷取陣列中第一個物件的 Token 屬性值
  3. 如果沒有找到資料時可以給予一個預設值

成功取出資料後就可以在後續測試情境中使用 ${tkn} 插入合法 token 值於設定中,我們將在下個測試情境中套用此變數來合法訪問 Web API。

 

建立HTTP要求 - 取得首頁資訊 (套用合法 token 值)


登入後當然就是要顯示首頁資訊,而目前系統驗證方式需在 HTTP 標頭中夾帶 token 值,因此建立一個 HTTP 標頭管理員 來設置相關資訊,其中當然包括上個步驟取得的 ${tkn} 變數囉。

接著建立兩個 HTTP 要求 來取得首頁資訊,在此就不贅述其內容。

 

建立HTTP要求 - 已登入用戶持續活動


因為要模擬用戶持續在線上活動,因此每位已登入用戶需要隨機執行 A / B 功能,且每隔 15 秒執行一次,不斷地執行到所有用戶登入完畢才停止,隨即完成所有測試情境。

分析一下需要處理的步驟如下:

  1. 建立一個無窮迴圈
  2. 在迴圈內隨機執行 A / B 功能
  3. 在迴圈內判斷最後一名用戶是否完成登入 (如果是就結束測試)
  4. 在迴圈內休息 15 秒鐘

 

首先建立 迴圈控制器 並設定迴圈次數為永久。

再建立一個 隨機控制器 表示會隨機執行此項目下的任一取樣功能。

於此控制器下加入兩個 HTTP 要求分別執行 A / B 功能,此設置表示會隨機執行任一功能。

再建立一個 若...控制器 判斷目前進入測試的虛擬用戶是否為最後一名用戶。

條件設定 ${__threadNum} == 500 表示若編號為 500 的虛擬用戶 (最後一位) 進入時符合條件。

當符合上述條件需中斷測試,因此在該控制器中加入 測試動作 項目來停止所有執行續,表示測試已經完成。

如果不是最後一位用戶,則不會觸發上述條件來中斷測試,因此再迴圈中加入 Think Time 項目作為迴圈等待時間,模擬用戶點選功能後閱讀相關資訊所停留的時間。

設置目前執行續暫停 15 秒鐘,表示該虛擬用戶會等待 15 秒後繼續接下來的測試。

模擬已登入用戶的持續活動行為所有設定如下。

 

完整測試情境


完整的測試情境如下,仔細看看其實還滿有結構性的,直接看此計畫項目應可直覺地了解測試步驟及情境。

 

完成測試及分析結果


執行結果顯示系統能在 120 秒內消化 500 個用戶湧入系統執行登入行為,並且在已登入用戶皆不定期操作系統特定功能 A 與 B 的情況下,所有用戶都可以在 1 秒內完成登入且看到首頁的所有資訊;在這個負載情境下均保持 0.00% 錯誤率,所有交易都可以在 500 ms 內反應,平均可以達到 24.1 TPS,若想進一步探究系統的效能極限,可以透過調整「虛擬用戶數量」及「湧入時間」作為變量,不斷提升對系統產生的壓力,如此就可以了解在效能恰好落入不可接受範圍時的數據為何,而該數據即為系統效能極限,如需突破則需再次進行效能分析,釐清是否已達硬體極限或是架構極限。 


希望此篇文章可以幫助到需要的人

若內容有誤或有其他建議請不吝留言給筆者喔 !