[JMeter]壓力測試 Hessian Service

[JMeter]壓力測試 Hessian Service

基本資料:

http://hessian.caucho.com/

http://jmeter.apache.org/usermanual/index.html

參考文件:

http://sunqi.iteye.com/blog/807475

http://henry-tech-notes.blogspot.com/2006/10/testing-hessian-services-with-jmeter.html

 

依照參考文件即可組合 jmeter + eclipse + hessian 的壓力測試環境.

 

中間遇到的問題:

1. 加入新的Java 要求及實作之類別, 執行後Console 未報錯, 報表亦未顯示任何執行結果:

A: 先查找 %JMETER_HOME%\bin\jmeter.log

2011/12/19 19:11:41 ERROR - jmeter.threads.JMeterThread: Test failed! java.lang.NoClassDefFoundError: com/caucho/hessian/client/HessianProxyFactory
    at HessianTest.setupTest(HessianTest.java:50)
    at org.apache.jmeter.protocol.java.sampler.JavaSampler.sample(JavaSampler.java:158)
    at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:411)
    at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:297)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: com.caucho.hessian.client.HessianProxyFactory
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 5 more

原來是我的 ANT 少加了一個服務依賴的JAR檔 (如: XXXInterface.jar ).

 

2. 整合進eclipse時, 找不到 NewDriver.class 去執行:

A: 文章有差異, 應該在 %JMETER_HOME%\bin\ApacheJMeter.jar 而非 %JMETER_HOME%\lib\ApacheJMeter_core.jar

 

3. 除錯模式時找不到新增的Source code:

A: 在Debug configuration > Source 按下 [Add], 選擇 Workspace Folder, 再選擇專案中的source folder.

 

快速步驟提示:

1. 建立PT 專案

2. 將所需Library 加入build path :

ApacheJMeter_core.jar
ApacheJMeter_java.jar
hessian-3.0.13.jar
XXXInterface.jar

3. 撰寫Java Code

// 繼承 Java 要求
public class HessianTest extends AbstractJavaSamplerClient
 
// 實作預設參數
@Override
public Arguments getDefaultParameters() 
 
// 初始化必要的物件: 如XXXService by HessianProxyFactory
@Override
public void setupTest(JavaSamplerContext context) {
 
// 實作測試案例
@Override
public SampleResult runTest(JavaSamplerContext arg0) {
 
 

4. 製作 ANT build.xml , 將專案編譯/包裝/佈署

    4.1 需加相依的專案元件檔一併放作%JMETER_HOME%\lib\ext. ps.sample 如附錄1

    4.2 此時已可以獨立執行%JMETER_HOME%\bin\jmeter.bat.

 

5. (option) 整合Eclipse

    5.1 以ApacheJmeter.jar 中的org.apache.jmeter.NewDriver.class 為主程式

    5.2 在Arguments:Tab 將Working directory 指到 %JMETER_HOME%\bin

    5.3 在Classpath:Tab 將default classpath 移除, 然後只增加一個 %JMETER_HOME%\bin\ApacheJMeter.jar

    5.4 在Source:Tab 將測試專案的source path 加入

 

====================

附錄1 – build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="SERVICE_PT"  basedir=".">
    <property file="build.properties"/>    
 
    <path id="classpath">
        <fileset dir="${dir.lib}">
            <include name="*.jar" />
        </fileset>
    </path>
    <target name="main" >
        <delete dir="${dir.temp}" />        
         <mkdir dir="${dir.temp}" />
        <copy todir="${dir.temp}">
            <fileset dir="${dir.src}" />
        </copy>
        <javac fork="true" debug="true" encoding="utf-8"
                destdir="${dir.temp}" includes="**/*.java" includeantruntime="on">
            <classpath refid="classpath"/>
            <src path="${dir.temp}"/>                            
        </javac>
        <jar destfile="${dir.temp}/${file.jar.name}" 
             basedir="${dir.temp}" 
             includes="**/*.class"
             excludes="**/*.jar" />
        <copy file="${dir.temp}/${file.jar.name}" todir="${dir.jmeter.lib.ext}" />        
         <delete file="${dir.temp}" />        
        <echo message="${timestamp}" />        
    </target>
</project>

 

附錄2 - sample code

   1:  public class HessianTest extends AbstractJavaSamplerClient {
   2:   
   3:      public static String P_Service_URL="Service URL";
   4:      public static String P_User_Name="User Name";
   5:      public static String P_Password="Password";
   6:      
   7:      
   8:      ISearch search = null;
   9:      
  10:      @Override
  11:      public Arguments getDefaultParameters() {
  12:          Arguments args = new Arguments();
  13:          args.addArgument(P_Service_URL, "http://localhost:8080/Search");
  14:          args.addArgument(P_User_Name, "ok");
  15:          args.addArgument(P_Password, "ok");
  16:          return args;
  17:      }
  18:   
  19:      @Override
  20:      public void setupTest(JavaSamplerContext context) {
  21:          String url = context.getParameter(P_Service_URL);
  22:          String user = context.getParameter(P_User_Name);
  23:          String password = context.getParameter(P_Password);
  24:          
  25:          try{
  26:              HessianProxyFactory factory = new HessianProxyFactory();
  27:              factory.setUser(user);
  28:              factory.setPassword(password);
  29:              searchParty = (ISearch) factory.create(ISearch.class ,url);            
  30:          }catch(Exception e){
  31:              e.printStackTrace();
  32:              throw new RuntimeException("Error getting hessian proxy", e);
  33:          }
  34:      }
  35:      
  36:   
  37:      @Override
  38:      public SampleResult runTest(JavaSamplerContext arg0) {
  39:          SampleResult result = generateSampleResult("Call Hessain Service");
  40:          result.sampleStart();
  41:          try{
  42:              RequestHeader requestHeader = setupRequestHeader();
  43:              ArrayList<RequestBody> requestBodys = setupRequestBody();
  44:                  
  45:              int i=0;
  46:              int errCount=0;
  47:              
  48:              for (RequestBody requestBody : requestBodys) {
  49:                  i++;
  50:                  SampleResult subResult = generateSampleResult("test." + i);
  51:                  result.addSubResult(subResult);
  52:                  
  53:                  subResult.sampleStart();
  54:                  try{
  55:                      ResponseMessage responseMessage = search.searchCustomer(requestHeader,requestBody);
  56:                      byte[] responseData = resultMessageSerialize(responseMessage).getBytes();            
  57:                      successHandler(subResult, 0, responseData);        
  58:                  }catch(Throwable e){
  59:                      errCount ++;                    
  60:                      exceptionHandler(subResult, e);            
  61:                  }
  62:                  subResult.sampleEnd();
  63:              }
  64:              successHandler(result, errCount, "".getBytes());
  65:          }catch (Exception e) {
  66:              exceptionHandler(result, e);                        
  67:          }
  68:          result.sampleEnd();
  69:          return result;
  70:      }
  71:      
  72:      private void successHandler(SampleResult result, int errCount, byte[] responseData){
  73:          boolean hadErr = errCount > 0;
  74:          if(hadErr){
  75:              result.setSuccessful(false);
  76:              result.setErrorCount(errCount);
  77:              result.setResponseMessage("Finish but had error.");
  78:          }else{
  79:              result.setSuccessful(true);
  80:              result.setResponseCodeOK();
  81:              result.setResponseMessage("Success");    
  82:          }
  83:          result.setResponseData(responseData);
  84:      }    
  85:      
  86:      private void exceptionHandler(SampleResult result, Throwable e){
  87:          result.setSuccessful(false);
  88:          result.setResponseMessage(e.getClass().getName() + " " + e.getLocalizedMessage());
  89:          result.setResponseData(exceptionSerialize(e).getBytes());
  90:      }
  91:      
  92:      private String exceptionSerialize(Throwable e){
  93:          StringWriter sw = new StringWriter();
  94:          e.printStackTrace(new PrintWriter(sw));
  95:          return sw.toString();
  96:      }
  97:  }