Jmeter二次開發——基於Java請求

溫一壺清酒發表於2020-12-18

簡述

這近幾年,越來越多非http的協議需要進行效能測試,包括不僅限於各類rpc、mq、快取等。對於這些協議,市面上可能沒有現成的工具可以直接使用,這個時候,我們可以自己動手,通過編寫相應的JavaSampler來高效地開展效能測試工作。

環境準備

  • java環境已搭建ok
  • jmeter環境已搭建ok
  • idea開發環境已配置ok

java和jmeter環境搭建,可參考Jmeter——環境搭建

二次開發

二次開發前提

  • 需要lib/ext中的ApacheJMeter_core.jar
  • 擴充套件java請求則還需要ApacheJMeter_java.jar
  • 擴充套件http請求則需要ApacheJMeter_http.jar

匯入jar包,自行匯入,可參考IDEA的基本操作——匯入匯出jar包

Jmeter Java Sampler

方法簡介

public Arguments getDefaultParameters();                   可選,定義可用引數及預設值,獲取介面的引數;
public void setupTest(JavaSamplerContext arg0);            可選,測試前執行,做一些初始化工作,類似於LR的init和Junit中的setUp();
public SampleResult runTest(JavaSamplerContext arg0);      必選,實現自定義請求,類似於LR的Action;
public void teardownTest(JavaSamplerContext arg0);         可選,測試結束時呼叫,類似於LR的end和Junit中的tearDown();

方法執行順序

getDefaultParameters() > setupTest(JavaSamplerContext arg0) > runTest(JavaSamplerContext arg0) > teardownTest(JavaSamplerContext arg0)

常用方法

  • addArgument("name", "value") 定義引數
  • sampleStart() 定義事務的開始,類似於LR的lr_start_transaction,和LR一樣事務間不要放無關程式碼
  • sampleEnd() 定義事務的結束,類似於LR的lr_end_transaction
  • setSuccessful(true、false) 設定執行結果的成功或失敗,Jmeter統計成功失敗的次數,在聚合報告中能夠體現。

類的繼承

在做二次開發的時候,大家都知道,自己定義的類需要繼承AbstractJavaSamplerClient,可為什麼要繼承這個類,而不是其他,想必大家也都知道。為了能看的更明白,我們直接來看程式碼,如下所示:

public abstract class AbstractJavaSamplerClient implements JavaSamplerClient {
    private static final Logger log = LoggerFactory.getLogger(AbstractJavaSamplerClient.class);
    private static final org.apache.log.Logger oldLogger = LoggingManager.getLoggerForClass();

    public AbstractJavaSamplerClient() {
    }

    public void setupTest(JavaSamplerContext context) {
        log.debug(this.getClass().getName() + ": setupTest");
    }

    public void teardownTest(JavaSamplerContext context) {
        log.debug(this.getClass().getName() + ": teardownTest");
    }

    public Arguments getDefaultParameters() {
        return null;
    }

    /** @deprecated */
    @Deprecated
    protected org.apache.log.Logger getLogger() {
        return oldLogger;
    }

    protected Logger getNewLogger() {
        return log;
    }
}

我們從上述程式碼看到有構造方法,3個普通方法,這3個方法是不是似曾相識?是的,在前文中就有提到。但發現,還少一個runTest方法,那它在哪呢?想必就是在這個類JavaSamplerClient中了。我們繼續來看程式碼,如下所示:

public interface JavaSamplerClient {
    void setupTest(JavaSamplerContext var1);

    SampleResult runTest(JavaSamplerContext var1);

    void teardownTest(JavaSamplerContext var1);

    Arguments getDefaultParameters();
}

好了,現在知道4個方法的來源了,在自己類中,實現功能,其實就是將這4個方法重寫,來實現自己的功能即可。思路有了,我們就來真實來寫個demo吧。

getDefaultParameters

編寫getDefaultParameters()方法,使用addArgument方法,設定入參,程式碼示例如下:

/**
     * 這個方法是用來自定義java方法入參的
     * params.addArgument("x","");表示入參名字叫x,預設值為空。
     * @return
     */
    @Override
    public Arguments getDefaultParameters() {
        Arguments params = new Arguments();
        params.addArgument("x","");
        return params;
    }

該引數設定,在jmeter介面中會展示,如下所示:

setupTest

setupTest,做自動化、效能測試都有類似概念,就是在測試前執行,做一些初始化工作。示例程式碼如下所示:

    /**
     * 每個執行緒測試前執行一次,做一些初始化工作
     * 獲取輸入的引數,賦值給變數,引數也可以在下面的runTest方法中獲取,這裡是為了展示該方法的作用
     * @param arg0
     */
    @Override
    public void setupTest(JavaSamplerContext arg0) {
        x = arg0.getParameter("x");
    }

runTest

runTest是程式碼邏輯處理部分,示例程式碼實現的功能就是做數字簡單的比較,demo而已,具體如下所示:

/**
     * 真正執行邏輯的方法
     * @param arg0
     * @return
     */
    @Override
    public SampleResult runTest(JavaSamplerContext arg0) {
        SampleResult sr = new SampleResult();
        sr.setSamplerData("請求引數x的值為:"+x);
        try {
            // jmeter 開始統計響應時間標記
            sr.sampleStart();
            int sum = Integer.parseInt(x);
            if (sum<0){
                logger.info(sum + "<0的值是"+ "-1");
                // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。
                sr.setResponseData("結果是:"+"-1", "utf-8");
                //設定響應失敗
                sr.setSuccessful(false);
            }
            else {
                String str = String.valueOf(x);
                final StringBuilder builder = new StringBuilder(str);
                if (builder.reverse().toString().equals(str)) {  //reverse 字串反轉,比如輸入66,反轉後為66,再做比較
                        logger.info(sum + ">0的值做比較後是"+ "0");
                        // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。
                        sr.setResponseData("結果是:"+"0", "utf-8");
                        sr.setDataType(SampleResult.TEXT);
                }else {
                    logger.info(sum + ">0的值是"+ "1");
                    // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。
                    sr.setResponseData("結果是:"+"1", "utf-8");
                }
                //設定響應執行成功
                sr.setSuccessful(true);

            }
            } catch (Throwable e) {
                //有異常,執行失敗
                sr.setSuccessful(false);
                e.printStackTrace();
            } finally {
            // jmeter 結束統計響應時間標記
            sr.sampleEnd();
        }
        return sr;
    }

teardownTest

teardownTest,與setupTest是對應關係,做自動化、效能測試都有類似概念,就是在測試結束後執行,做一些清理工作。示例程式碼如下所示:

/**
     * 測試結束後呼叫
     * @param arg0
     */
    @Override
    public void teardownTest(JavaSamplerContext arg0) {
        SampleResult sr = new SampleResult();
        logger.info("測試結束");
        // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。
        sr.setResponseData("測試結束", "utf-8");
    }

完成程式碼編寫後,可以先除錯一波,確保正確後,匯出jar包,放到jmeter對應目錄lib/ext下。匯出jar包的操作,可參考IDEA的基本操作——匯入匯出jar包

實際效果

說了這麼多,我們來執行下程式碼看下實際效果,啟動jmeter,新增java 請求,並選擇剛編寫的java方法,如下所示:

輸出為-1

先來演示輸出為-1的效果,我們可以從程式碼中看出,結果為-1,輸入值小於0即可。

我們入參-9,如下所示:

執行程式碼,通過結果樹檢視請求資料,如下所示:

檢視響應資料,如下所示:

我們看介面響應情況,響應是失敗的,為啥是失敗的呢?我們從程式碼可知,入參小於0時,強制設定成了響應失敗,執行效果如下所示:

輸出為1

再來演示輸出為1的效果,我們可以從程式碼中看出,結果為1,輸入值大於0即可。

我們入參78,如下所示:

執行程式碼,通過結果樹檢視請求資料,如下所示:

檢視響應資料,響應的狀態也是成功的,如下所示:

輸出等於0

最後演示下輸出為0的效果,我們可以從程式碼中看出,結果為0,輸入值轉換後還相等,則輸出為0。

我們入參66,如下所示:

執行程式碼,通過結果樹檢視請求資料,如下所示:

檢視響應資料,響應的狀態也是成功的,如下所示:

完整程式碼

再貼下今天演示demo的完整程式碼,如下所示:

import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.protocol.java.test.JavaTest;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

/**
 * @author_router:wenyihuqingjiu
 * @date:2020-12-18
 * 
 */

public class PalindromeDemo extends AbstractJavaSamplerClient {
    private static Logger logger = LogManager.getLogger(PalindromeDemo.class.getName());
    private String x;

    /**
     * 這個方法是用來自定義java方法入參的
     * params.addArgument("x","");表示入參名字叫x,預設值為空。
     * @return
     */
    @Override
    public Arguments getDefaultParameters() {
        Arguments params = new Arguments();
        params.addArgument("x","");
        return params;
    }

    /**
     * 每個執行緒測試前執行一次,做一些初始化工作
     * 獲取輸入的引數,賦值給變數,引數也可以在下面的runTest方法中獲取,這裡是為了展示該方法的作用
     * @param arg0
     */
    @Override
    public void setupTest(JavaSamplerContext arg0) {
        x = arg0.getParameter("x");
    }

    /**
     * 真正執行邏輯的方法
     * @param arg0
     * @return
     */
    @Override
    public SampleResult runTest(JavaSamplerContext arg0) {
        SampleResult sr = new SampleResult();
        sr.setSamplerData("請求引數x的值為:"+x);
        try {
            // jmeter 開始統計響應時間標記
            sr.sampleStart();
            int sum = Integer.parseInt(x);
            if (sum<0){
                logger.info(sum + "<0的值是"+ "-1");
                // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。
                sr.setResponseData("結果是:"+"-1", "utf-8");
                //設定響應失敗
                sr.setSuccessful(false);
            }
            else {
                String str = String.valueOf(x);
                final StringBuilder builder = new StringBuilder(str);
                if (builder.reverse().toString().equals(str)) {  //reverse 字串反轉,比如輸入66,反轉後為66,再做比較
                        logger.info(sum + ">0的值做比較後是"+ "0");
                        // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。
                        sr.setResponseData("結果是:"+"0", "utf-8");
                        sr.setDataType(SampleResult.TEXT);
                }else {
                    logger.info(sum + ">0的值是"+ "1");
                    // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。
                    sr.setResponseData("結果是:"+"1", "utf-8");
                }
                //設定響應執行成功
                sr.setSuccessful(true);

            }
            } catch (Throwable e) {
                //有異常,執行失敗
                sr.setSuccessful(false);
                e.printStackTrace();
            } finally {
            // jmeter 結束統計響應時間標記
            sr.sampleEnd();
        }
        return sr;
    }

    /**
     * 測試結束後呼叫
     * @param arg0
     */
    @Override
    public void teardownTest(JavaSamplerContext arg0) {
        SampleResult sr = new SampleResult();
        logger.info("測試結束");
        // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。
        sr.setResponseData("測試結束", "utf-8");
    }
    
}

問題總結

執行程式碼,報錯提示沒有LoggerFactory,報錯如下所示:

解決辦法:重新下載slf4j包即可。

以上就是今天的分享內容了,二次開發java請求,小小demo,有誤之處,望批評指正。

相關文章