強大的擴展性是壓力測試工具 JMeter 的一個重要特點。雖然本身內置的函數、協議支持有限,但是 JMeter 提供了良好的擴展框架,允許使用者對其進行擴展。
本文將介紹如何利用 JMeter 的擴展性來實現自定義的函數,用户可以通過此方式擴展出性能測試過程中所需要的函數功能。
對於 JMeter 瞭解不多的讀者,可參閲往期內容:開源測試工具 JMeter 介紹
JMeter 函數簡介
由於 JMeter 函數相對簡單,本文便以它作為起點。
JMeter 函數(function)可以讓用户在編輯測試腳本的時候插入到任何 Sampler 或者其他測試元素中,執行相應的任務。比如,__machineName 取得 JMeter Agent 所在機器的主機名,__machineIP 取得 JMeter Agent 所在機器的 IP 地址,__RandomString 得到一個隨機的字符串。JMeter 所提供的內置函數完整列表,請參考官方文檔。
總體來説,擴展 JMeter 的函數可以分成下面幾個步驟:
- 在 IDE (以下將以 Eclipse 為例)中新建 Maven 項目,引入擴展 JMeter 函數所需的依賴;
- 編寫實現自定義函數的代碼,並對其編譯打包;
- 將編譯好的包拷貝至 JMeter 的擴展目錄,編輯測試腳本,在腳本中使用自定義的函數;
- 運行自定義的函數,查看運行結果是否正確。
接下來我們將以一個返回隨機偶數的自定義函數為例,來帶大家瞭解完整的開發過程。
創建擴展 JMeter 項目
本例中將使用 Maven 來管理依賴並進行打包。
在 Eclipse 中新建一個 Maven 項目:File > New > Project,選擇 Maven Project,如下圖所示:
在嚮導的第 2 頁裏,選擇 Create a simple project (skip archetype selection),使用默認的 Workspace,或指定 Workspace 位置,並點擊下一步:
在嚮導的第 3 頁,指定 Group Id 和 Artifact Id。點擊完成,完成項目的創建:
通過 Maven 引入相應的 JMeter 依賴
打開 pom.xml ,在 中加入 JMeter 的 ApacheJMeter_core 和 ApacheJMeter_functions 依賴,如下所示:
<dependencies>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_core</artifactId>
<version>5.4.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_functions</artifactId>
<version>5.4.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
由於 ApacheJMeter_core 和 ApacheJMeter_functions 已經包含在 JMeter 的運行時中,所以後面編譯打包出來的 jar 不需要包含它們,此處將這兩個依賴的 scope 設為 provided。
保存 pom.xml 後,如果 Maven 沒有開始自動下載相關的依賴文件,在項目上右鍵點擊,選擇 Maven > Update Project,完成依賴的下載。
擴展 JMeter 函數
要實現擴展 JMeter 函數,有兩處要點:
- 實現函數功能的類所在的 package 的聲明必須包含".functions"
- 實現類繼承 org.apache.jmeter.functions.AbstractFunction,並且編寫相應方法的實現邏輯。
package 名字
JMeter 可以通過非 UI 方式運行,因為它的設計中讓一些核心的類(非 UI 相關的,比如 ApacheJMeter_core 等)可以在非 UI 運行方式下被優先加載進來,加載這些類的時候是通過命名規則來實現的。所有實現 JMeter 函數的類必須包含".functions.",因此我們自定義實現的類裏也必須遵守這一規則,比如,類所在的 package 名稱為"com.xmeter.customized.functions"。當然也可以通過更改 jmeter.properties 中的配置來實現改變命名規則,如下圖所示(但一般來説不推薦更改此項配置):
classfinder.functions.contain=.functions.
擴展 AbstractFunction 類
ApacheJMeter_core 中的 AbstractFunction 類提供了4個抽象方法,在擴展的時候需要實現它們。
方法 1:
public String execute(SampleResult previousResult, Sampler currentSampler) throws InvalidVariableException;
JMeter 會將上次運行的 SampleResult 和當前的 Sampler 作為參數傳入 execute 方法中,方法的返回值就是在運行該函數後應得到的值,返回類型為 String 類型。該方法如果操作了非線程安全的對象(比如文件),則需要對該方法進行線程同步保護。
方法 2:
public List<String> getArgumentDesc();
getArgumentDesc 方法用於告訴 JMeter 關於你實現的函數所需的參數的描述。
方法 3:
public void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException;
setParameters 方法用於傳遞用户在執行過程中傳入的函數所需的實際參數值。該方法在函數沒有參數的情況下也會被調用。一般該方法傳入的參數會被保存在實現類中的全局變量裏,並在其後 JMeter 調用到 execute 方法時使用到。
方法 4:
public String getReferenceKey();
getReferenceKey 方法返回的就是此處自定義的函數的名字。JMeter 約定的命名規則是在函數名前面加入雙下劃線"__"。建議函數的名字跟實現類的類名保持一致,而且 getReferenceKey 方法返回的名字以 static final 的方式在實現類中定義好,避免在運行的時候更改它。
源代碼實現
實現的源代碼如下所示,重要的代碼已經有註釋。
package com.emqx.xmeter.demo.functions;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.functions.AbstractFunction;
import org.apache.jmeter.functions.InvalidVariableException;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;
public class MyRandomFunc extends AbstractFunction {
//自定義function的描述
private static final List<String> desc = new LinkedList<String>();
static {
desc.add("Get a random int within specified parameter value.");
}
//function名稱
private static final String KEY = "__MyRandomFunc";
private static final int MAX_PARA_COUNT = 1;
private static final int MIN_PARA_COUNT = 1;
//傳入參數的值
private Object[] values;
private Random r = new Random();
@Override
public List<String> getArgumentDesc() {
return desc;
}
@Override
public String execute(SampleResult previousResult, Sampler currentSampler) throws InvalidVariableException {
try {
int max = new Integer(((CompoundVariable) values[0]).execute().trim());
int val = r.nextInt(max);
return String.valueOf(val);
} catch(Exception ex) {
throw new InvalidVariableException(ex);
}
}
@Override
public String getReferenceKey() {
return KEY;
}
@Override
public void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException {
checkParameterCount(parameters, MIN_PARA_COUNT, MAX_PARA_COUNT); //檢查參數的個數是否正確
values = parameters.toArray(); //將值存入類變量中
}
}
編譯並拷貝到 JMeter 擴展目錄
接下來的一步就是要把實現類編譯生成 jar 包並且拷貝到 JMeter 的擴展目錄。編譯打包部分可參考以下的 Maven :
<build>
<finalName>my-demo-plugins-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<!-- 打包方式 -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase><!-- 綁定到package階段上 -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
接下來在 Eclipse 中新增一個 Maven Build 的運行配置,請參見下圖:
運行上面這個 Maven Build 之後,在工程的 target 目錄下,會發現新生成了 my-demo-plugins-0.0.1-SNAPSHOT-jar-with-dependencies.jar。把這個jar 拷貝至 $JMETER_HOME/lib/ext 目錄下($JMETER_HOME 指 JMeter 的安裝目錄),重新啓動 JMeter。
點擊工具 > 函數助手對話框,如果配置正確的話就能出現自己定義的函數,如下圖所示。點擊右下角的"生成"按鈕,會生成調用該函數後生成的示例結果。
測試自定義函數
最後我們創建一個測試,來驗證該 JMeter 函數工作是否正常,我們將使用 Dummy Sampler 作為測試用的取樣器。Dummy Sampler 是一個第三方擴展的取樣器,提供基本的請求和響應模擬功能,在腳本調試或 JMeter 學習期間可以作為簡單的模擬數據生成器來使用。Dummy Sampler 在 JMeter 社區中可以找到,我們先介紹一下它的安裝方法。
Dummy Sampler 可以通過 JMeter 插件管理器完成安裝。
- 點擊以下鏈接下載:https://jmeter-plugins.org/get/
- 將下載的 jmeter-plugins-manager-1.7 放到 $JMETER_HOME/lib/ext 目錄下,並重啓 JMeter。
- 如果安裝成功,重啓 JMeter 後,菜單"選項"中將出現"Plugins Manager":
- 打開"Plugins Manager"後,選擇"Available Plugins",在左側的列表中搜索並選擇"Dummy Sampler",然後點擊"Apply Changes and Restart JMeter"按鈕。如下圖所示:
- JMeter的Plugins Manager 將下載相關文件,並且在安裝完成後自動重啓 JMeter。打開"Plugins Manager"後,將發現"Dummy Sampler"已出現在"Installed Plugins"中。
接下來,我們在測試腳本中使用 Dummy Sampler。先在線程組中添加 > 取樣器 > jp@gc - Dummy Sampler:
可以進一步設置請求內容、連接時間、延遲時間、響應時間、響應碼、響應內容等模擬數據。在這次測試中,我們將自定義函數生成的隨機數設置為響應內容,參數設為 100,也就是指定生成小於 100 的偶數。
為方便查看測試結果,添加監聽器,如"察看結果樹"。然後運行測試,如果一切正常,在"響應數據"部分應該就能看到由該函數生成的隨機整數了。
版權聲明: 本文為 EMQ 原創,轉載請註明出處。
原文鏈接:https://www.emqx.com/zh/blog/jmeter-extension-development-custom-functions