JMeter擴展插件實現(xiàn)對自定義協(xié)議進行支持

本文版權歸xmeter.net 所有。歡迎轉載,轉載請注明出處。

摘要##

JMeter本身提供了插件機制,允許第三方擴展JMeter以支持JMeter不支持的協(xié)議的測試。本文以擴展一個簡單的Apache Kafka producer sampler為例描述了如何對JMeter進行擴展,方便地實現(xiàn)對新協(xié)議的支持。

Kafka簡介##

Apache Kafka是由Apache軟件基金會開發(fā)的一個開源消息系統(tǒng)項目。Kafka最初是由LinkedIn開發(fā),并于2011年初開源。2012年10月從Apache孵化器畢業(yè)。該項目的目標是為處理實時數據提供一個統(tǒng)一、高通量、低等待的平臺。

如下圖所示,Kafka的producer(數據生產者)通過Socket向Kafka集群上配置好的主題(topic)發(fā)送數據,consumer(數據消費者)在另外一端消費由生產者那邊產生的數據,并進行業(yè)務的處理。Kafka作為一個優(yōu)秀的消息處理系統(tǒng),在集群配置,主題管理等方面有很多需要深入理解和優(yōu)化等地方,本文的重點是JMeter的擴展,以Kafka的生產者為例來描述如何利用JMeter來模擬大量的生產者的調用,更多關于Kafka的細節(jié)請參考它的官方文檔

Kafka生產、消費者模型

準備工作##

擴展實現(xiàn)JMeter插件之前,需要先考慮清楚哪些選項需要暴露給測試人員。就像HTTP測試中,需要讓用戶輸入服務器地址,端口號,路徑等,同線程組里的連接是否共用等,如果提供是否共用連接這種選項的話,也需要在界面中體現(xiàn),當然實現(xiàn)插件的時候處理連接的代碼也會有所不同。

往Kafka上發(fā)送消息的時候,需要提供一些基本配置信息(實際Kafka的生產者配置不止這些),如果讀者對下面所說的內容不了解也不要緊,只需要理解準備這些的目的是為了將這些配置信息提供給Kafka測試人員,在開始測試之前可以針對被測系統(tǒng)進行配置。

  1. 服務器所在地址,在Kafka中稱之為Brokers
  2. 發(fā)送的主題的名字
  3. Message Serializer,消息通過網絡發(fā)送,需要將其序列化,這里指定的是消息序列化的方式
  4. Key Serializer,Kafka發(fā)送消息的時候,可以指定Key,Key Serializer的主要作用是指定Key的序列化方式
  5. 發(fā)送的消息

下圖是本文最終完成的JMeter Kafka插件的截圖,測試開始之前需要輸入上文所列的信息。


Kafka JMeter插件截圖

JMeter插件實現(xiàn)步驟1 - 準備開發(fā)環(huán)境##

JMeter插件實現(xiàn)是標準的Java代碼,打開Eclipse(作者使用的是4.5.2),新建一個Maven項目。我們的項目中需要引用到JMeter本身提供的一些庫,包括ApacheJMeter_core和ApacheJmeter_java,并且對JMeter的版本依賴是3.0。另外,還需要對Kafka的類庫也需要引入,pom.xml中依賴部分的代碼如下。

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jmeter-version>3.0</jmeter-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_core</artifactId>
            <version>${jmeter-version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_java</artifactId>
            <version>${jmeter-version}</version>
            <scope>provided</scope>
        </dependency>
        
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka_2.9.2</artifactId>
            <version>0.8.1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

工程創(chuàng)建完畢之后,開始編寫代碼來實現(xiàn)插件。

JMeter插件實現(xiàn)步驟2 - 自定義界面##

JMeter的插件機制會在$JMETER_HOME/lib/ext目錄下去動態(tài)加載符合指定條件的JAR包,并在JMeter中顯示出來。比如要擴展UI的話,擴展的Java類的包名必須是”.gui.”,同樣的擴展函數的Java類的包名必須是”.function.”.

新建一個類,org.apache.jmeter.protocol.kafka.control.gui.KafkaSamplerUI,并指定其父類為AbstractSamplerGui。該類需要實現(xiàn)以下的功能:

1)界面布局與控件。JMeter的界面是標準的Swing,所以里面的控件和布局都是標準的Swing寫法。
2)界面與Sampler之間的數據交換。Sampler在JMeter中繼承的是TestElement,用戶輸入的數據都是保存在Sampler中的,因此可以認為這個是界面的模型。界面與模型(Sampler)之間的數據交換需要實現(xiàn)父類的下面幾個方法,

public void configure(TestElement el)

該方法用于把Sampler中的數據加載到界面中。在實現(xiàn)自己的邏輯之前,先調用一下父類的方法super.configure(el),這樣可以確??蚣茏詣訛槟慵虞d一些缺省數據,比如Sampler的名字。

public void modifyTestElement(TestElement e)

這個方法用于把界面的數據移到Sampler中,剛好與上面的方法相反。在調用自己的實現(xiàn)方法之前,請先調用一下super.configureTestElement(e),這個會幫助移到一些缺省的數據。

public TestElement createTestElement()

該方法創(chuàng)建一個新的Sampler,然后將界面中的數據設置到這個新的Sampler實例中。

public void clearGui()

該方法會在reset新界面的時候調用,這里可以填入界面控件中需要顯示的一些缺省的值。

在本文的實現(xiàn)中,分別實現(xiàn)上面的那些方法,包括顯示5個控件(4個控制參數的控件在一個panel里,發(fā)送的消息的控件在另外一個panel里),以及另外的幾個方法用于和Sampler之間的數據交換等。完整的代碼請參見這里。

JMeter插件實現(xiàn)步驟3 - 自定義Kafka Sampler##

新建一個Sampler,org.apache.jmeter.protocol.kafka.sampler.KafkaSampler,并指定其父類為AbstractSampler。該類需要實現(xiàn)以下的功能:

1)增加一些getter/setter方法,這些方法用于與UI之間的數據交換,這些數據在用戶保存/打開腳本的時候將被自動序列化/反序列化。
2)實現(xiàn)sample方法:

public SampleResult sample(Entry entry)

該方法是JMeter實現(xiàn)對目標系統(tǒng)發(fā)起請求實際工作的地方。主要的工作是記錄請求處理時間,對返回結果進行處理和判斷,并根據處理結果返回SampleResult,該SampleResult中需要指定返回的內容是否成功,以及消息等。該方法的基本實現(xiàn)框架如下所示:

    public SampleResult sample(Entry entry) {
        SampleResult result = new SampleResult();
        result.setSampleLabel(getName());
        try {
            result.sampleStart();
            //對目標系統(tǒng)發(fā)出測試請求
            result.sampleEnd();
            result.setSuccessful(true);
            result.setResponseCodeOK();
        } catch (Exception e) {
            result.sampleEnd(); // stop stopwatch
            result.setSuccessful(false);
            result.setResponseMessage("Exception: " + e);
            // get stack trace as a String to return as document data
            java.io.StringWriter stringWriter = new java.io.StringWriter();
            e.printStackTrace(new java.io.PrintWriter(stringWriter));
            result.setResponseData(stringWriter.toString(), null);
            result.setDataType(org.apache.jmeter.samplers.SampleResult.TEXT);
            result.setResponseCode("FAILED");
        }
        return result;
    }

本文的實現(xiàn)中,生成一個Kafka的Producer對象,并將用戶界面里指定的信息發(fā)送到Kafka服務器上。完整的代碼請參見這里。

JMeter插件實現(xiàn)步驟4 - 打包、部署##

打包過程與普通的Maven項目相似,但是需要注意的是本插件需要把Kafka相關的依賴庫文件也一并打入,否則還需要單獨準備所依賴的JAR包。因此在pom.xml中加入下面的build插件。右擊工程 》Run As 》Maven install,運行成功后,在工程的target目錄下會生成一個kafka_jmeter-jar-with-dependencies.jar,這個就是我們打好的插件。

    <build>
        <finalName>${project.artifactId}</finalName>
        <defaultGoal>install</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</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>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

插件開發(fā)完成后,將kafka_jmeter-jar-with-dependencies.jar拷貝到$JMETER_HOME/lib/ext目錄下,如果之前已經打開了JMeter,則需要將JMeter關閉重啟。

JMeter插件實現(xiàn)步驟5 - 測試插件##

新建一個測試腳本,加入一個線程組,然后添加一個Sampler,如果運行正常,在子菜單中應該能看到我們擴展出來的“Kafka Sampler”。

開發(fā)好的插件

修改一下線程組里的線程數,則能實現(xiàn)多虛擬用戶的并發(fā)測試了。下圖是“查看結果樹”里面顯示的內容。

查看結果樹中的內容

下圖是Kafka的消費者端,能看到相關的消息已經發(fā)送成功。

服務器端控制臺輸出

更多擴展方式##

如本文所示,如果通過比較“標準”的方式來擴展JMeter對新協(xié)議的測試,還是有一定的工作量,特別是如果界面功能比較豐富的話,實現(xiàn)界面的那個類會比較復雜。如果對界面的要求不是很高,那么還有一種比較簡單的可選項是通過擴展AbstractJavaSamplerClient,通過擴展該類,可以實現(xiàn)對簡單的測試配置屬性進行設置,并在runTest方法的實現(xiàn)中對目標系統(tǒng)發(fā)出請求

public SampleResult runTest(JavaSamplerContext context)

該方法的返回值是SampleResult,就是驗證測試結果,與上文中實現(xiàn)步驟3比較類似。讀者可以參見本文的參考資料中關于AbstractJavaSamplerClient中列出的幾篇文章。

大規(guī)模自定義協(xié)議測試 - XMeter幫您提高效率,降低成本##

如果用戶自定義的協(xié)議的測試,單臺機器能夠模擬的客戶端是有限的,如果針對大規(guī)模的協(xié)議測試(比如本文舉例的Kafka),可能需要準備大量的測試機器對被測系統(tǒng)進行打壓,這個過程需要大量的準備機器環(huán)境,以及管理這些環(huán)境的工作,導致工作效率比較低、而且容易出錯。XMeter將這些過程遷移至云端,彈性伸縮管理這些壓力機,用戶只要關注測試腳本的實現(xiàn)過程,而無需關心這些測試環(huán)境的管理,從而大大降低了大規(guī)模性能測試的復雜度。另外XMeter提供了豐富的測試報告,讓性能問題一目了然。

參考資料##

JMeter擴展官方文檔
AbstractJavaSamplerClient的方式擴展JMeter文章1
AbstractJavaSamplerClient的方式擴展JMeter文章2
AbstractJavaSamplerClient的方式擴展JMeter文章3

關于我們##

XMeter成立于2016年,核心團隊都來自于IBM,是一家領先技術的性能測試持續(xù)集成咨詢與服務提供商。我們致力于提供給客戶可靠,簡單,低成本的性能測試解決方案。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容