本文版權(quán)歸xmeter.net 所有。歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處。
摘要##
JMeter本身提供了插件機(jī)制绪氛,允許第三方擴(kuò)展JMeter以支持JMeter不支持的協(xié)議的測試。本文以擴(kuò)展一個(gè)簡單的Apache Kafka producer sampler為例描述了如何對JMeter進(jìn)行擴(kuò)展涝影,方便地實(shí)現(xiàn)對新協(xié)議的支持枣察。
Kafka簡介##
Apache Kafka是由Apache軟件基金會(huì)開發(fā)的一個(gè)開源消息系統(tǒng)項(xiàng)目。Kafka最初是由LinkedIn開發(fā)袄琳,并于2011年初開源询件。2012年10月從Apache孵化器畢業(yè)。該項(xiàng)目的目標(biāo)是為處理實(shí)時(shí)數(shù)據(jù)提供一個(gè)統(tǒng)一唆樊、高通量宛琅、低等待的平臺(tái)。
如下圖所示逗旁,Kafka的producer(數(shù)據(jù)生產(chǎn)者)通過Socket向Kafka集群上配置好的主題(topic)發(fā)送數(shù)據(jù)嘿辟,consumer(數(shù)據(jù)消費(fèi)者)在另外一端消費(fèi)由生產(chǎn)者那邊產(chǎn)生的數(shù)據(jù),并進(jìn)行業(yè)務(wù)的處理片效。Kafka作為一個(gè)優(yōu)秀的消息處理系統(tǒng)红伦,在集群配置,主題管理等方面有很多需要深入理解和優(yōu)化等地方淀衣,本文的重點(diǎn)是JMeter的擴(kuò)展昙读,以Kafka的生產(chǎn)者為例來描述如何利用JMeter來模擬大量的生產(chǎn)者的調(diào)用,更多關(guān)于Kafka的細(xì)節(jié)請參考它的官方文檔
準(zhǔn)備工作##
擴(kuò)展實(shí)現(xiàn)JMeter插件之前蛮浑,需要先考慮清楚哪些選項(xiàng)需要暴露給測試人員。就像HTTP測試中只嚣,需要讓用戶輸入服務(wù)器地址沮稚,端口號,路徑等册舞,同線程組里的連接是否共用等蕴掏,如果提供是否共用連接這種選項(xiàng)的話,也需要在界面中體現(xiàn),當(dāng)然實(shí)現(xiàn)插件的時(shí)候處理連接的代碼也會(huì)有所不同盛杰。
往Kafka上發(fā)送消息的時(shí)候挽荡,需要提供一些基本配置信息(實(shí)際Kafka的生產(chǎn)者配置不止這些),如果讀者對下面所說的內(nèi)容不了解也不要緊即供,只需要理解準(zhǔn)備這些的目的是為了將這些配置信息提供給Kafka測試人員徐伐,在開始測試之前可以針對被測系統(tǒng)進(jìn)行配置。
- 服務(wù)器所在地址募狂,在Kafka中稱之為Brokers
- 發(fā)送的主題的名字
- Message Serializer办素,消息通過網(wǎng)絡(luò)發(fā)送,需要將其序列化祸穷,這里指定的是消息序列化的方式
- Key Serializer性穿,Kafka發(fā)送消息的時(shí)候,可以指定Key雷滚,Key Serializer的主要作用是指定Key的序列化方式
- 發(fā)送的消息
下圖是本文最終完成的JMeter Kafka插件的截圖需曾,測試開始之前需要輸入上文所列的信息。
JMeter插件實(shí)現(xiàn)步驟1 - 準(zhǔn)備開發(fā)環(huán)境##
JMeter插件實(shí)現(xiàn)是標(biāo)準(zhǔn)的Java代碼祈远,打開Eclipse(作者使用的是4.5.2)呆万,新建一個(gè)Maven項(xiàng)目。我們的項(xiàng)目中需要引用到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)建完畢之后缎除,開始編寫代碼來實(shí)現(xiàn)插件严就。
JMeter插件實(shí)現(xiàn)步驟2 - 自定義界面##
JMeter的插件機(jī)制會(huì)在$JMETER_HOME/lib/ext目錄下去動(dòng)態(tài)加載符合指定條件的JAR包,并在JMeter中顯示出來器罐。比如要擴(kuò)展UI的話梢为,擴(kuò)展的Java類的包名必須是”.gui.”,同樣的擴(kuò)展函數(shù)的Java類的包名必須是”.function.”.
新建一個(gè)類轰坊,org.apache.jmeter.protocol.kafka.control.gui.KafkaSamplerUI铸董,并指定其父類為AbstractSamplerGui。該類需要實(shí)現(xiàn)以下的功能:
1)界面布局與控件衰倦。JMeter的界面是標(biāo)準(zhǔn)的Swing袒炉,所以里面的控件和布局都是標(biāo)準(zhǔn)的Swing寫法旁理。
2)界面與Sampler之間的數(shù)據(jù)交換樊零。Sampler在JMeter中繼承的是TestElement,用戶輸入的數(shù)據(jù)都是保存在Sampler中的,因此可以認(rèn)為這個(gè)是界面的模型驻襟。界面與模型(Sampler)之間的數(shù)據(jù)交換需要實(shí)現(xiàn)父類的下面幾個(gè)方法夺艰,
public void configure(TestElement el)
該方法用于把Sampler中的數(shù)據(jù)加載到界面中。在實(shí)現(xiàn)自己的邏輯之前沉衣,先調(diào)用一下父類的方法super.configure(el)郁副,這樣可以確保框架自動(dòng)為你加載一些缺省數(shù)據(jù)豌习,比如Sampler的名字存谎。
public void modifyTestElement(TestElement e)
這個(gè)方法用于把界面的數(shù)據(jù)移到Sampler中,剛好與上面的方法相反肥隆。在調(diào)用自己的實(shí)現(xiàn)方法之前既荚,請先調(diào)用一下super.configureTestElement(e),這個(gè)會(huì)幫助移到一些缺省的數(shù)據(jù)栋艳。
public TestElement createTestElement()
該方法創(chuàng)建一個(gè)新的Sampler恰聘,然后將界面中的數(shù)據(jù)設(shè)置到這個(gè)新的Sampler實(shí)例中。
public void clearGui()
該方法會(huì)在reset新界面的時(shí)候調(diào)用吸占,這里可以填入界面控件中需要顯示的一些缺省的值晴叨。
在本文的實(shí)現(xiàn)中,分別實(shí)現(xiàn)上面的那些方法矾屯,包括顯示5個(gè)控件(4個(gè)控制參數(shù)的控件在一個(gè)panel里兼蕊,發(fā)送的消息的控件在另外一個(gè)panel里),以及另外的幾個(gè)方法用于和Sampler之間的數(shù)據(jù)交換等件蚕。完整的代碼請參見這里遍略。
JMeter插件實(shí)現(xiàn)步驟3 - 自定義Kafka Sampler##
新建一個(gè)Sampler,org.apache.jmeter.protocol.kafka.sampler.KafkaSampler骤坐,并指定其父類為AbstractSampler绪杏。該類需要實(shí)現(xiàn)以下的功能:
1)增加一些getter/setter方法,這些方法用于與UI之間的數(shù)據(jù)交換纽绍,這些數(shù)據(jù)在用戶保存/打開腳本的時(shí)候?qū)⒈蛔詣?dòng)序列化/反序列化蕾久。
2)實(shí)現(xiàn)sample方法:
public SampleResult sample(Entry entry)
該方法是JMeter實(shí)現(xiàn)對目標(biāo)系統(tǒng)發(fā)起請求實(shí)際工作的地方。主要的工作是記錄請求處理時(shí)間拌夏,對返回結(jié)果進(jìn)行處理和判斷僧著,并根據(jù)處理結(jié)果返回SampleResult,該SampleResult中需要指定返回的內(nèi)容是否成功障簿,以及消息等盹愚。該方法的基本實(shí)現(xiàn)框架如下所示:
public SampleResult sample(Entry entry) {
SampleResult result = new SampleResult();
result.setSampleLabel(getName());
try {
result.sampleStart();
//對目標(biāo)系統(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;
}
本文的實(shí)現(xiàn)中,生成一個(gè)Kafka的Producer對象站故,并將用戶界面里指定的信息發(fā)送到Kafka服務(wù)器上皆怕。完整的代碼請參見這里毅舆。
JMeter插件實(shí)現(xiàn)步驟4 - 打包、部署##
打包過程與普通的Maven項(xiàng)目相似愈腾,但是需要注意的是本插件需要把Kafka相關(guān)的依賴庫文件也一并打入憋活,否則還需要單獨(dú)準(zhǔn)備所依賴的JAR包。因此在pom.xml中加入下面的build插件虱黄。右擊工程 》Run As 》Maven install悦即,運(yùn)行成功后,在工程的target目錄下會(huì)生成一個(gè)kafka_jmeter-jar-with-dependencies.jar橱乱,這個(gè)就是我們打好的插件辜梳。
<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目錄下泳叠,如果之前已經(jīng)打開了JMeter冗美,則需要將JMeter關(guān)閉重啟。
JMeter插件實(shí)現(xiàn)步驟5 - 測試插件##
新建一個(gè)測試腳本析二,加入一個(gè)線程組粉洼,然后添加一個(gè)Sampler,如果運(yùn)行正常叶摄,在子菜單中應(yīng)該能看到我們擴(kuò)展出來的“Kafka Sampler”属韧。
修改一下線程組里的線程數(shù),則能實(shí)現(xiàn)多虛擬用戶的并發(fā)測試了蛤吓。下圖是“查看結(jié)果樹”里面顯示的內(nèi)容宵喂。
下圖是Kafka的消費(fèi)者端,能看到相關(guān)的消息已經(jīng)發(fā)送成功会傲。
更多擴(kuò)展方式##
如本文所示锅棕,如果通過比較“標(biāo)準(zhǔn)”的方式來擴(kuò)展JMeter對新協(xié)議的測試,還是有一定的工作量淌山,特別是如果界面功能比較豐富的話裸燎,實(shí)現(xiàn)界面的那個(gè)類會(huì)比較復(fù)雜。如果對界面的要求不是很高泼疑,那么還有一種比較簡單的可選項(xiàng)是通過擴(kuò)展AbstractJavaSamplerClient德绿,通過擴(kuò)展該類,可以實(shí)現(xiàn)對簡單的測試配置屬性進(jìn)行設(shè)置退渗,并在runTest方法的實(shí)現(xiàn)中對目標(biāo)系統(tǒng)發(fā)出請求
public SampleResult runTest(JavaSamplerContext context)
該方法的返回值是SampleResult移稳,就是驗(yàn)證測試結(jié)果,與上文中實(shí)現(xiàn)步驟3比較類似会油。讀者可以參見本文的參考資料中關(guān)于AbstractJavaSamplerClient中列出的幾篇文章个粱。
大規(guī)模自定義協(xié)議測試 - XMeter幫您提高效率,降低成本##
如果用戶自定義的協(xié)議的測試翻翩,單臺(tái)機(jī)器能夠模擬的客戶端是有限的都许,如果針對大規(guī)模的協(xié)議測試(比如本文舉例的Kafka)稻薇,可能需要準(zhǔn)備大量的測試機(jī)器對被測系統(tǒng)進(jìn)行打壓,這個(gè)過程需要大量的準(zhǔn)備機(jī)器環(huán)境梭稚,以及管理這些環(huán)境的工作,導(dǎo)致工作效率比較低絮吵、而且容易出錯(cuò)弧烤。XMeter將這些過程遷移至云端,彈性伸縮管理這些壓力機(jī)蹬敲,用戶只要關(guān)注測試腳本的實(shí)現(xiàn)過程暇昂,而無需關(guān)心這些測試環(huán)境的管理,從而大大降低了大規(guī)模性能測試的復(fù)雜度伴嗡。另外XMeter提供了豐富的測試報(bào)告急波,讓性能問題一目了然。
參考資料##
JMeter擴(kuò)展官方文檔
AbstractJavaSamplerClient的方式擴(kuò)展JMeter文章1
AbstractJavaSamplerClient的方式擴(kuò)展JMeter文章2
AbstractJavaSamplerClient的方式擴(kuò)展JMeter文章3
關(guān)于我們##
XMeter成立于2016年瘪校,核心團(tuán)隊(duì)都來自于IBM澄暮,是一家領(lǐng)先技術(shù)的性能測試持續(xù)集成咨詢與服務(wù)提供商。我們致力于提供給客戶可靠,簡單,低成本的性能測試解決方案阱扬。