JMeter擴充套件開發:自定義函式

emqx發表於2022-10-13

強大的擴充套件性是壓力測試工具 JMeter 的一個重要特點。雖然本身內建的函式、協議支援有限,但是 JMeter 提供了良好的擴充套件框架,允許使用者對其進行擴充套件。

本文將介紹如何利用 JMeter 的擴充套件性來實現自定義的函式,使用者可以透過此方式擴充套件出效能測試過程中所需要的函式功能。

對於 JMeter 瞭解不多的讀者,可參閱往期內容:開源測試工具 JMeter 介紹

JMeter 函式簡介

由於 JMeter 函式相對簡單,本文便以它作為起點。

JMeter 函式(function)可以讓使用者在編輯測試指令碼的時候插入到任何 Sampler 或者其他測試元素中,執行相應的任務。比如,__machineName 取得 JMeter Agent 所在機器的主機名,__machineIP 取得 JMeter Agent 所在機器的 IP 地址,__RandomString 得到一個隨機的字串。JMeter 所提供的內建函式完整列表,請參考官方文件

總體來說,擴充套件 JMeter 的函式可以分成下面幾個步驟:

  1. 在 IDE (以下將以 Eclipse 為例)中新建 Maven 專案,引入擴充套件 JMeter 函式所需的依賴;
  2. 編寫實現自定義函式的程式碼,並對其編譯打包;
  3. 將編譯好的包複製至 JMeter 的擴充套件目錄,編輯測試指令碼,在指令碼中使用自定義的函式;
  4. 執行自定義的函式,檢視執行結果是否正確。

接下來我們將以一個返回隨機偶數的自定義函式為例,來帶大家瞭解完整的開發過程。

建立擴充套件 JMeter 專案

本例中將使用 Maven 來管理依賴並進行打包。

在 Eclipse 中新建一個 Maven 專案:File > New > Project,選擇 Maven Project,如下圖所示:
1

在嚮導的第 2 頁裡,選擇 Create a simple project (skip archetype selection),使用預設的 Workspace,或指定 Workspace 位置,並點選下一步:
2

在嚮導的第 3 頁,指定 Group Id 和 Artifact Id。點選完成,完成專案的建立:
3

透過 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 函式,有兩處要點:

  1. 實現函式功能的類所在的 package 的宣告必須包含".functions"
  2. 實現類繼承 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 的執行配置,請參見下圖:
4

執行上面這個 Maven Build 之後,在工程的 target 目錄下,會發現新生成了 my-demo-plugins-0.0.1-SNAPSHOT-jar-with-dependencies.jar。把這個jar 複製至 $JMETER_HOME/lib/ext 目錄下($JMETER_HOME 指 JMeter 的安裝目錄),重新啟動 JMeter。

點選工具 > 函式助手對話方塊,如果配置正確的話就能出現自己定義的函式,如下圖所示。點選右下角的"生成"按鈕,會生成呼叫該函式後生成的示例結果。
5

測試自定義函式

最後我們建立一個測試,來驗證該 JMeter 函式工作是否正常,我們將使用 Dummy Sampler 作為測試用的取樣器。Dummy Sampler 是一個第三方擴充套件的取樣器,提供基本的請求和響應模擬功能,在指令碼除錯或 JMeter 學習期間可以作為簡單的模擬資料生成器來使用。Dummy Sampler 在 JMeter 社群中可以找到,我們先介紹一下它的安裝方法。

Dummy Sampler 可以透過 JMeter 外掛管理器完成安裝。

  1. 點選以下連結下載:https://jmeter-plugins.org/get/
  2. 將下載的 jmeter-plugins-manager-1.7 放到 $JMETER_HOME/lib/ext 目錄下,並重啟 JMeter。
  3. 如果安裝成功,重啟 JMeter 後,選單"選項"中將出現"Plugins Manager":6
  4. 開啟"Plugins Manager"後,選擇"Available Plugins",在左側的列表中搜尋並選擇"Dummy Sampler",然後點選"Apply Changes and Restart JMeter"按鈕。如下圖所示:7
  5. JMeter的Plugins Manager 將下載相關檔案,並且在安裝完成後自動重啟 JMeter。開啟"Plugins Manager"後,將發現"Dummy Sampler"已出現在"Installed Plugins"中。

接下來,我們在測試指令碼中使用 Dummy Sampler。先線上程組中新增 > 取樣器 > jp@gc - Dummy Sampler:
8

可以進一步設定請求內容、連線時間、延遲時間、響應時間、響應碼、響應內容等模擬資料。在這次測試中,我們將自定義函式生成的隨機數設定為響應內容,引數設為 100,也就是指定生成小於 100 的偶數。
9

為方便檢視測試結果,新增監聽器,如"察看結果樹"。然後執行測試,如果一切正常,在"響應資料"部分應該就能看到由該函式生成的隨機整數了。
10

版權宣告: 本文為 EMQ 原創,轉載請註明出處。

原文連結:https://www.emqx.com/zh/blog/jmeter-extension-development-custom-functions

相關文章