博客 / 詳情

返回

JMeter擴展開發:自定義函數

強大的擴展性是壓力測試工具 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

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.