Jmeter“Java請求”使用總結

    xiaoxiao2026-05-23  3

    转自 http://blog.csdn.net/wanglha/article/details/42777579 1. 線程組,在我們測試方案裏面,每個線程模擬一個用戶,執行用戶的登錄、等等等一系列的操作。由於我們的項目是長連接的,如何能實現多個sample公用一個長連接客戶端,考慮了很久,最後實現方法如下: 1. 線程組,在我們測試方案裏面,每個線程模擬一個用戶,執行用戶的登錄、等等等一系列的操作。由於我們的項目是長連接的,如何能實現多個sample公用一個長連接客戶端,考慮了很久,最後實現方法如下:  1  package tea.client.network;  2  /**  3   *  @author  Teaey  4   * @creation 2012-8-25  5    */  6  public  class NetworkClientHolder  7 {  8      /**  9       * 這裏使用ThradLocal存儲BaseClient 10       * 方便一輪測試的每個sample都是由同一個socketChannel發送 11       * 更真實的模擬用戶 12        */ 13      private  static ThreadLocal<BaseClient> clientHolder =  new ThreadLocal<BaseClient>(); 14      public  static BaseClient getClient(String ip, String port) 15     { 16         BaseClient client = clientHolder.get(); 17          if ( null == client) 18         { 19             client =  new BaseClient(ip, port); 20             client.connect(); 21             clientHolder.set(client); 22         } 23          return client; 24     } 25 } 26  代碼中使用thread_local保存Socket客戶端,這样每個sample中發送數據的客戶端都是從這裏拿的,就可以保證長連接的情況下,socket不會重复創建,很好的模擬了用戶。 當然不單單是鏈接可以保存,所有需要在線程中共享的數據都可以通過這種方法來實現。 2. 接下來是如何封裝發送請求的客戶端,這裏用的netty,具體可以根據項目情況使用mina或者nio都可以。代碼直接明了^_^:   1  package tea.client.network;   2    3  import java.net.InetSocketAddress;   4  import java.util.concurrent.Executors;   5  import org.jboss.netty.bootstrap.ClientBootstrap;   6  import org.jboss.netty.channel.Channel;   7  import org.jboss.netty.channel.ChannelFuture;   8  import org.jboss.netty.channel.ChannelHandlerContext;   9  import org.jboss.netty.channel.ChannelPipeline;  10  import org.jboss.netty.channel.ChannelPipelineFactory;  11  import org.jboss.netty.channel.ChannelStateEvent;  12  import org.jboss.netty.channel.Channels;  13  import org.jboss.netty.channel.ExceptionEvent;  14  import org.jboss.netty.channel.MessageEvent;  15  import org.jboss.netty.channel.SimpleChannelHandler;  16  import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;  17  import tea.common.network.ClientDecoder;  18  import tea.common.network.ClientEncoder;  19  import tea.common.network.ClientMessage;  20   21  /**  22   *  @author  Teaey  23   * @creation 2012-8-25  24    */  25  public  class BaseClient  26 {  27      public BaseClient(String ip, String port)  28     {  29          this.ip = ip;  30          this.port = port;  31     }  32      private String           ip;  33      private String           port;  34      private Channel          channel;  35      private ClientBootstrap  bootstrap;  36      private Object           syn             =  new Object();  37      private  static  final  int Receive_Timeout = 10000;        // ms  38      private ClientMessage    response        =  null;  39      public  void connect()  40     {  41         bootstrap =  new ClientBootstrap( new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));  42         bootstrap.setOption("tcpNoDelay",  true);  43         bootstrap.setPipelineFactory( new ClientPipelineFactory());  44          while ( true)  45         {  46             ChannelFuture future = bootstrap.connect( new InetSocketAddress(ip, Integer.parseInt(port)));  47             future.awaitUninterruptibly(5000);  48              if (future.isDone())  49             {  50                 channel = future.getChannel();  51                  if (channel !=  null && channel.isConnected())  52                 {  53                      break;  54                 }  55             }  56         }  57     }  58      public  void disconnect()  59     {  60          if (channel.isConnected())  61         {  62             channel.disconnect();  63         }  64     }  65      public  boolean isConnected()  66     {  67          return channel.isConnected();  68     }  69      public  void close()  70     {  71          if ( this.channel.isOpen())  72         {  73              this.channel.close();  74         }  75         bootstrap.releaseExternalResources();  76     }  77      /**  78       * 發送消息,無需返回  79        */  80      public  void send(ClientMessage message)  81     {  82         channel.write(message);  83     }  84      /**  85       * 發送消息,等待返回  86        */  87      public ClientMessage sendWaitBack(ClientMessage message)  88     {  89         response =  null;  90          try  91         {  92             channel.write(message);  93              synchronized (syn)  94             {  95                  try  96                 {  97                     syn.wait(Receive_Timeout);  98                 }  catch (InterruptedException e)  99                 { 100                     e.printStackTrace(); 101                 } 102             } 103              if ( null == response) 104             { 105                 System.err.println("Receive response timeout"); 106             } 107         }  catch (Exception e) 108         { 109             e.printStackTrace(); 110         } 111          return response; 112     } 113      class ClientPipelineFactory  implements ChannelPipelineFactory 114     { 115          public ChannelPipeline getPipeline()  throws Exception 116         { 117             ChannelPipeline p = Channels.pipeline(); 118             p.addLast("frameDecoder",  new ClientDecoder()); 119             p.addLast("fremeEncoder",  new ClientEncoder()); 120             p.addLast("logicHandler",  new ClientMsgHandler()); 121              return p; 122         } 123     } 124      class ClientMsgHandler  extends SimpleChannelHandler 125     { 126          public  void messageReceived(ChannelHandlerContext ctx, MessageEvent e)  throws Exception 127         { 128             Object obj = e.getMessage(); 129              if (obj  instanceof ClientMessage) 130             { 131                 ClientMessage msg = (ClientMessage) obj; 132                 response = msg; 133                  synchronized (syn) 134                 { 135                     syn.notifyAll(); 136                 } 137             } 138         } 139          public  void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)  throws Exception 140         { 141             System.out.println("connected server:" + ctx.getChannel()); 142         } 143          public  void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e)  throws Exception 144         { 145             System.out.println("disconnected server:" + ctx.getChannel()); 146         } 147          public  void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)  throws Exception 148         { 149             System.out.println("Error in exceptionCaught:" + e.getCause()); 150         } 151     } 152 } 153  這段代碼展示了我們的客戶端,這裏所有的請求有兩種發送模式,一種是發送並阻塞等待返回( sendWaitBack ),第二種就是直接發送( send )。 3. 有了發送請求的客戶端,那如何能夠更簡單的實現一個協議好讓客戶端發送,再貼一段代碼^_^:   1  package tea.client.network;   2    3  import org.apache.jmeter.config.Arguments;   4  import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;   5  import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;   6  import org.apache.jmeter.samplers.SampleResult;   7  import com.google.protobuf.InvalidProtocolBufferException;   8  import com.google.protobuf.MessageLite;   9   10  /**  11   *  @author  Teaey  12   * @creation 2012-8-25  13    */  14  public  abstract  class BaseSample  extends AbstractJavaSamplerClient  15 {  16      public  static  final String PARAM_IP   = "ip";  17      public  static  final String PARAM_PORT = "port";  18      public  static  final String VAR_IP     = "${ip}";  19      public  static  final String VAR_PORT   = "${port}";  20      protected BaseClient       client;  21      public  void addParameter(Arguments params)  22     {  23     }  24      /**  25       * Jmeter獲取消息参數,默認配置ip和port兩個参數  26       * 如果子類有更多参數,調用super.getDefaultParameters()獲取Arguments後,繼續設置其他方法  27        */  28     @Override  29      public Arguments getDefaultParameters()  30     {  31         System.out.println("1.getDefaultParameters");  32         Arguments params =  new Arguments();  33         params.addArgument(PARAM_IP, VAR_IP);  34         params.addArgument(PARAM_PORT, VAR_PORT);  35         addParameter(params);  36          return params;  37     }  38      /**  39       * runTest的前置方法  40        */  41     @Override  42      public  void setupTest(JavaSamplerContext context)  43     {  44         System.out.println("2.setupTest:" + context.containsParameter(PARAM_IP));  45         String ip = context.getParameter(PARAM_IP);  46         String port = context.getParameter(PARAM_PORT);  47          this.client = NetworkClientHolder.getClient(ip, port);  48         System.out.println("thread--->" + Thread.currentThread().getId() + " client--->" + client);  49     }  50      /**  51       * Jmeter調用,用於實際的測試  52        */  53     @Override  54      public SampleResult runTest(JavaSamplerContext context)  55     {  56         SampleResult sample = getSample();  57         sample.sampleStart();  58          try  59         {  60             MessageLite response = doTest();  61             String msg = response ==  null ? "" : response.toString();  62             sample.setResponseMessage(msg);  63             sample.setSuccessful( true);  64         }  catch (Exception e)  65         {  66             sample.setSuccessful( false);  67             e.printStackTrace();  68         }  finally  69         {  70             sample.sampleEnd();  71         }  72          return sample;  73     }  74      /**  75       * 獲取本Sample的標簽,子類實現  76        */  77      public  abstract String getLabel();  78      /**  79       * 獲取一個帶標簽的Sample   80        */  81      public SampleResult getSample()  82     {  83         SampleResult sample =  new SampleResult();  84         sample.setSampleLabel(getLabel());  85          return sample;  86     }  87      /**  88       * Jmeter調用,用於  89        */  90     @Override  91      public  void teardownTest(JavaSamplerContext context)  92     {  93         System.out.println("4.teardownTest");  94     }  95      /**  96       * 需實現,具體測試的方法,調用client的send/sendWithBack發送請求  97       * 如無返回,放回null即可   98        */  99      public  abstract MessageLite doTest()  throws InvalidProtocolBufferException; 100 } 好的,這裏封裝了下AbstractJavaSamplerClient,每個消息默認包含ip和port参數,這可以再jmeter的用戶變量中定義好。为了方便大家添加消息的参數,這裏實現了空的 addParameter(Arguments params)方法,這样在具體消息中直接重寫這個方法,來添加具體的参數。是不是很方便?^_^,具體協議還需要實現的兩個方法分別是:getLabel和 doTest。第一個方法時用於報告顯示的請求名字,一般定義为消息名字+“Label”就OKay。第二個方法就是我們重點重寫的方法,這裏再貼段代碼,是一個具體消息的實現:  1  package tea.client;  2   3  import com.google.protobuf.InvalidProtocolBufferException;  4  import com.google.protobuf.MessageLite;  5  import tea.client.network.BaseSample;  6  import tea.common.network.ClientMessage;  7  import tea.common.network.RPC.HeartBeat_C2S;  8  import tea.common.network.RPC.HeartBeat_S2C;  9  10  /** 11   *  @author  Teaey 12   * @creation 2012-8-24 13    */ 14  public  class HeartBeatSample  extends BaseSample 15 { 16     @Override 17      public MessageLite doTest()  throws InvalidProtocolBufferException 18     { 19         HeartBeat_C2S.Builder request = HeartBeat_C2S.newBuilder(); 20         request.setTimestamp(System.currentTimeMillis()); 21         ClientMessage cm =  new ClientMessage(); 22         cm.setContent(request.build().toByteArray()); 23         cm.setName("HeartBeat"); 24         ClientMessage sm = client.sendWaitBack(cm); 25         HeartBeat_S2C response = HeartBeat_S2C.parseFrom(sm.getContent()); 26          return response; 27     } 28     @Override 29      public String getLabel() 30     { 31          return "HeartBeatSample"; 32     } 33 } 34  可以看到doTest的工作就是封裝請求,並拿到父類的client發送,然後返回響應(send方式返回null),Okay,大功告成。
    转载请注明原文地址: https://ju.6miu.com/read-1309981.html
    最新回复(0)