開源壓力測試工具JMeter使用介紹

最近須要對改造的redis緩存接口作壓力測試,使用了開源壓力測試工具JMeter,分享一下本身的使用經驗,但願能對須要進行壓力測試的開發同窗有所幫助。java

JMeter介紹redis

JMeter是Apache軟件基金會下的一款開源壓力測試工具,官方網址是:http://jmeter.apache.org/。JMeter能夠測試靜態、動態資源的性能,這些資源包括文件、Servlets 、Perl腳本、Java對象、數據庫、FTP服務器等,並生成圖形報告。JMeter使用Java開發,既支持可視化界面操做,也支持命令行操做。spring

Java請求測試(界面操做)數據庫

因爲須要對改造的redis緩存接口測試,所以使用了JMeter的Java請求測試,安裝和使用步驟以下所示(以Windows操做系統爲例,並默認已安裝、配置Java運行環境)。apache

1)從官網上下載JMeter並解壓,例如解壓至C:\apache-jmeter-2.9。緩存

2)配置JMeter環境變量,增長變量JMETER_HOME,值爲「C:\apache-jmeter-2.9」,修改變量CLASSPATH,增長「%JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;% JMETER_HOME%\lib\jorphan.jar;%JMETER_HOME%\lib\logkit-1.2.jar;」服務器


3)執行JMeter目錄下的bin\jmeter.bat,顯示JMeter界面說明安裝成功。併發

4)新建Java工程,在該工程中,引入JMeter目錄下lib中的jar包,繼承JMeter的AbstractJavaSamplerClient類,在子類中重寫setupTest、teardownTest、getDefaultParameters、runTest方法,實現對緩存接口的get、set、hGet、hSet方法進行測試,子類代碼以下所示。app

package com.sohu.cms.test;
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.samplers.SampleResult; 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.sohu.cms.datacache.DataCache;
import com.sohu.cms.datacache.DataCacheManager;
/**
 * 繼承jmeter的AbstractJavaSamplerClient類,
 * 重寫setupTest、teardownTest、getDefaultParameters、runTest方法
 * 對緩存接口的get、set、hGet、hSet方法進行測試
 * @author wang
 *
 */
public class TestDataCacheClient extends AbstractJavaSamplerClient{
    private static long start = 0; 
    private static long end = 0; 
                                                             
    private static DataCacheManager dataCacheManager;
    private static DataCache dataCache;
    private static int size = 8192;
    private static String method = "get";
    private static Object key = "TEST_KEY";
    private static Object field = "TEST_FIELD";
    private static Object value = new Byte[size];
                                                             
    //此處初始化咱們改造的redis緩存接口dataCache
    static {
        ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
        dataCacheManager = (DataCacheManager) context.getBean("dataCacheManager");
        dataCache = dataCacheManager.getObjectDataCache(); 
    }
    /**
     * 測試開始
     */ 
    public void setupTest(JavaSamplerContext arg0) {       
        start = System.currentTimeMillis(); 
    } 
    /**
     * 測試結束
     */ 
    public void teardownTest(JavaSamplerContext arg0) {
        end = System.currentTimeMillis(); 
        System.out.println("[method=" + method + "] [size=" + size + "] [time:" + (end - start) / 1000); 
    } 
    /**
     * 添加參數默認值,參數默認值會在界面中顯示
     */
    public Arguments getDefaultParameters() {
        //添加兩個參數,
        //size爲測試value值的字節大小,默認爲8192字節
        //method爲須要進行測試的緩存接口方法,默認爲get
        Arguments args = new Arguments();
        args.addArgument("size", "8192");
        args.addArgument("method","get");
        return args; 
    } 
    /**
     * 測試
     */ 
    public SampleResult runTest(JavaSamplerContext arg0) {
        //獲取界面或測試計劃配置文件(jmx)中傳入的參數
        if (arg0.getParameter("method") != null) method = arg0.getParameter("method");
        if (arg0.getIntParameter("size") > 0) size = arg0.getIntParameter("size");
        value = new Byte[size];
                                                                 
        SampleResult sr = new SampleResult(); 
        try {
            boolean result = true;
            //根據傳入的method參數測試相應的緩存接口方法
            if (method.equals("get")){
                //測試用例的核心邏輯
                //測試用例開始
                sr.sampleStart();
                //測試用例執行
                result = get();
                //測試用例結果
                sr.setSuccessful(result);
                //測試用例結束
                sr.sampleEnd();
            } else if (method.equals("set")) {
                sr.sampleStart();
                result = set();
                sr.setSuccessful(result);
                sr.sampleEnd();
            } else if (method.equals("hGet")) {
                sr.sampleStart();
                result = hGet();
                sr.setSuccessful(result);
                sr.sampleEnd();
            } else if (method.equals("hSet")) {
                sr.sampleStart();
                result = hSet();
                sr.setSuccessful(result);
                sr.sampleEnd();
            }
        } catch (Exception e) { 
             e.printStackTrace(); 
        } 
        return sr; 
    }
                                                             
    /**
     * 緩存接口get方法測試用例
     * @return
     */
    public boolean get() {
        boolean result = true;
        try {
            dataCache.get(key);
        } catch (Exception e) {
            System.out.println(e);
            result = false;
        }
        return result;
    }
                                                             
    /**
     * 緩存接口set方法測試用例
     * @return
     */
    public boolean set() {
        boolean result = true;
        try {
            dataCache.put(key, value);
        } catch (Exception e) {
            System.out.println(e);
            result = false;
        }
        return result;
    }
                                                             
    /**
     * 緩存接口hGet方法測試用例
     * @return
     */
    public boolean hGet() {
        boolean result = true;
        try {
            dataCache.hGet(key, field);
        } catch (Exception e) {
            System.out.println(e);
            result = false;
        }
        return result;
    }
                                                             
    /**
     * 緩存接口hSet方法測試用例
     * @return
     */
    public boolean hSet() {
        boolean result = true;
        try {
            result = dataCache.hSet(key, field, value);
        } catch (Exception e) {
            System.out.println(e);
            result = false;
        }
        return result;
    }
}

5)將工程以jar包形式導出,置於JMeter目錄lib\ext下,並將工程依賴的jar包置於JMeter目錄lib下,啓動JMeter。右鍵「測試計劃」添加「線程組」。右鍵「線程組」添加「Java請求」,右鍵「Java請求」添加「聚合報告」。ide

6)在「Java請求」中選擇所寫的測試類,並能夠設置相關參數,在「線程組」中能夠設置併發線程數和循環次數,點擊上方「啓動」按鈕開始測試,測試完成後,能夠在「聚合報告」中查看到測試結果。

Java請求測試(命令行操做)

JMeter也支持命令行操做,在服務器上進行測試時,咱們就採用了這種方式。一個簡單的JMeter命令行操做以下所示(在JMeter目錄bin下執行)。

Windows下: JMeter-n –t test.jmx -l result.jtl

Linux下: ./jmeter.sh -n –t test.jmx -l result.jtl

其中-n 表示命令行執行,test.jmx爲測試計劃配置文件,result.jtl爲測試結果。

可在界面中進行測試計劃配置,而後保存即可生成jmx格式文件,以下所示。

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.4" jmeter="2.9 r1437961">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="測試計劃" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用戶定義的變量" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="線程組" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循環控制器" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <!-- 循環次數 -->
          <stringProp name="LoopController.loops">100</stringProp>
        </elementProp>
        <!-- 併發線程數 -->
        <stringProp name="ThreadGroup.num_threads">100</stringProp>
        <stringProp name="ThreadGroup.ramp_time">100</stringProp>
        <longProp name="ThreadGroup.start_time">1376103961000</longProp>
        <longProp name="ThreadGroup.end_time">1376103961000</longProp>
        <boolProp name="ThreadGroup.scheduler">false</boolProp>
        <stringProp name="ThreadGroup.duration"></stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
      </ThreadGroup>
      <hashTree>
        <JavaSampler guiclass="JavaTestSamplerGui" testclass="JavaSampler" testname="Java請求" enabled="true">
          <elementProp name="arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" enabled="true">
            <!-- 自定義參數 -->
            <collectionProp name="Arguments.arguments">
              <elementProp name="size" elementType="Argument">
                <stringProp name="Argument.name">size</stringProp>
                <stringProp name="Argument.value">8192</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
              </elementProp>
              <elementProp name="method" elementType="Argument">
                <stringProp name="Argument.name">method</stringProp>
                <stringProp name="Argument.value">set</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
              </elementProp>
            </collectionProp>
          </elementProp>
          <stringProp name="classname">com.sohu.cms.test.TestDataCacheClient</stringProp>
        </JavaSampler>
        <hashTree>
          <ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="聚合報告" enabled="true">
            <boolProp name="ResultCollector.error_logging">false</boolProp>
            <objProp>
              <name>saveConfig</name>
              <value class="SampleSaveConfiguration">
                <time>true</time>
                <latency>true</latency>
                <timestamp>true</timestamp>
                <success>true</success>
                <label>true</label>
                <code>true</code>
                <message>true</message>
                <threadName>true</threadName>
                <dataType>true</dataType>
                <encoding>false</encoding>
                <assertions>true</assertions>
                <subresults>true</subresults>
                <responseData>false</responseData>
                <samplerData>false</samplerData>
                <xml>false</xml>
                <fieldNames>false</fieldNames>
                <responseHeaders>false</responseHeaders>
                <requestHeaders>false</requestHeaders>
                <responseDataOnError>false</responseDataOnError>
                <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
                <assertionsResultsToSave>0</assertionsResultsToSave>
                <bytes>true</bytes>
              </value>
            </objProp>
            <stringProp name="filename"></stringProp>
          </ResultCollector>
          <hashTree/>
        </hashTree>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

result.ftl爲按行輸出的測試執行結果,以下所示,可在界面操做的聚合報告導入該文件從而生成聚合報告。

...

1376040889436,48,Java請求,,,線程組1-40,,true,0,0

1376040889792,9,Java請求,,,線程組1-7,,true,0,0

1376040889526,167,Java請求,,,線程組1-57,,true,0,0

1376040889791,10,Java請求,,,線程組 1-54,,true,0,0

...

相關文章
相關標籤/搜索