您的位置:軟件測(cè)試 > 開源軟件測(cè)試 > 開源性能測(cè)試工具 > Jmeter
學(xué)習(xí)使用Jmeter做壓力測(cè)試(一)--壓力測(cè)試基本概念
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2016/6/20 14:39:41 ] 推薦標(biāo)簽:性能測(cè)試工具 Jmeter

  一、性能測(cè)試的概念
  性能測(cè)試是通過(guò)自動(dòng)化的測(cè)試工具模擬多種正常峰值及異常負(fù)載條件來(lái)對(duì)系統(tǒng)的各項(xiàng)性能指標(biāo)進(jìn)行測(cè)試。負(fù)載測(cè)試壓力測(cè)試都屬于性能測(cè)試,兩者可以結(jié)合進(jìn)行。
  通過(guò)負(fù)載測(cè)試,確定在各種工作負(fù)載下系統(tǒng)的性能,目標(biāo)是當(dāng)負(fù)載逐漸增加時(shí),測(cè)試系統(tǒng)各項(xiàng)性能指標(biāo)的變化情況。壓力測(cè)試時(shí)通過(guò)確定一個(gè)系統(tǒng)的瓶頸或者不能接受的
  性能點(diǎn),來(lái)獲取系統(tǒng)能提供的大服務(wù)級(jí)別的測(cè)試。性能測(cè)試主要包括負(fù)載測(cè)試、強(qiáng)度測(cè)試、容量測(cè)試。
  二、性能測(cè)試的指標(biāo)
  web服務(wù)器:
  Avg Rps: 平均每秒的響應(yīng)次數(shù) = 總請(qǐng)求數(shù) /秒數(shù);
  Avg time to last byte per terstion(mstes): 平均每秒業(yè)務(wù)腳本的迭代次數(shù);
  Successful Rounds: 成功的請(qǐng)求;
  Failed Rounds: 失敗的請(qǐng)求;
  Successful Hits: 成功的點(diǎn)擊次數(shù);
  Failed Hits: 失敗的點(diǎn)擊次數(shù);
  Hits Per Second: 每秒點(diǎn)擊次數(shù);
  Successful Hits Per Second:每秒成功的點(diǎn)擊次數(shù);
  Failed Hits Per Second: 每秒失敗的點(diǎn)擊次數(shù);
  Attempted Connections: 嘗試連接數(shù);
  Throughput: 吞吐率;
  數(shù)據(jù)庫(kù)服務(wù)器:
  User Connections: 用戶連接數(shù),也是數(shù)據(jù)庫(kù)的連接數(shù)量;
  Number of Deadlocks: 數(shù)據(jù)庫(kù)死鎖;
  Butter Cache Hit: 數(shù)據(jù)庫(kù)Cache 的命中情況;
  三、性能測(cè)試的流程
  1.明確性能測(cè)試需求;
  2.制定性能測(cè)試方案;
  2.1.測(cè)試范圍
  2.2.入口標(biāo)準(zhǔn)
  2.3.出口標(biāo)準(zhǔn)
  2.4.測(cè)試策略(測(cè)試環(huán)境指標(biāo)、存量數(shù)據(jù)、業(yè)務(wù)場(chǎng)景、測(cè)試通過(guò)標(biāo)準(zhǔn)等)
  2.5.測(cè)試風(fēng)險(xiǎn)
  2.6.測(cè)試資源        
  3.設(shè)計(jì)性能測(cè)試用例;
  4.執(zhí)行性能測(cè)試用例;
  5.分析性能測(cè)試結(jié)果;
  6.生成性能測(cè)試報(bào)告;
  四、性能測(cè)試的工具--JMeter
  為什么是JMeter而不是LoadRunner呢  1.更少的投入,針對(duì)有限的測(cè)試成本;  2.開源工具的可定制性無(wú)可比擬;  3.通過(guò)社區(qū)得到大程度的支持。
  JMeter是Apache組織開發(fā)的基于Java的壓力測(cè)試工具。初被設(shè)計(jì)用于web應(yīng)用的測(cè)試,后來(lái)擴(kuò)展到其他測(cè)試領(lǐng)域。可用于測(cè)試靜態(tài)和動(dòng)態(tài)資源,如文件、Java服務(wù)
  程序、Java對(duì)象、數(shù)據(jù)庫(kù)等。JMeter能夠?qū)?yīng)用程序做功能/回歸測(cè)試,通過(guò)創(chuàng)建帶有斷言的腳本來(lái)驗(yàn)證被測(cè)程序返回了期望的結(jié)果。而且為了保證大限度的靈活性,
  JMeter允許使用正則表達(dá)式創(chuàng)建斷言。
  五、JMeter的特性
  1.支持對(duì)多種服務(wù)類型進(jìn)行測(cè)試;
  2.支持通過(guò)錄制/回訪方式獲取測(cè)試腳本;
  3.具備高可移植性,是純Java 程序;
  4.采用多線程框架,允許通過(guò)多個(gè)線程并發(fā)取樣及通過(guò)獨(dú)立的線程組對(duì)不同的功能同時(shí)取樣;
  5.精心設(shè)計(jì)的GUI支持高速用戶操作和精確計(jì)時(shí);
  6.支持緩存和離線的方式分析/回放測(cè)試結(jié)果;
  7.高擴(kuò)展性;
  六、JMeter常用測(cè)試元件
  1.線程組
  用來(lái)管理執(zhí)行性能測(cè)試所需的JMeter線程。
  a.可以設(shè)置線程數(shù)量
  b.設(shè)置線程啟動(dòng)周期
  c.設(shè)置執(zhí)行測(cè)試腳本的循環(huán)次數(shù)
  2.控制器
  JMeter有兩種類型的控制器:采樣器和邏輯控制器。
  采樣器被用來(lái)向服務(wù)器發(fā)送請(qǐng)求。JMeter采樣器包含:FTP Request、HTTP Request、JDBC Request等。
  邏輯控制器用來(lái)控制JMeter的測(cè)試邏輯,特別是何時(shí)發(fā)送請(qǐng)求。
  3.監(jiān)聽器
  監(jiān)聽器提供了對(duì)JMeter在測(cè)試期間收集到的信息的訪問(wèn)方法。
  4.定時(shí)器
  JMeter線程在發(fā)送請(qǐng)求之間沒(méi)有間歇,通過(guò)添加定時(shí)器,設(shè)定請(qǐng)求之間應(yīng)該間隔的時(shí)間。
  5.斷言
  可以使用斷言來(lái)檢查從服務(wù)器獲得的響應(yīng)內(nèi)容。
  6.配置元件
  配置元件與采樣器緊密關(guān)聯(lián)。雖然配置元件并不發(fā)送請(qǐng)求,但可添加或修改請(qǐng)求。
  7.前置處理器
  會(huì)在采樣器發(fā)出請(qǐng)求之前做一些操作。
  8.后置處理器
  會(huì)在采樣器發(fā)出請(qǐng)求之后做一些操作。
  JMeter執(zhí)行順序:配置元件=》前置處理器=》定時(shí)器=》采樣器=》后置處理器=》斷言=》監(jiān)聽器
  七、輔助測(cè)試工具開發(fā)
  下面的代碼(工具:sqlexec)是一個(gè)用來(lái)向數(shù)據(jù)庫(kù)(目前支持Oracle、MySQL)插入測(cè)試數(shù)據(jù)的工具。支持多線程,可插入千萬(wàn)級(jí)別測(cè)試數(shù)據(jù)。在后續(xù)壓測(cè)中會(huì)用到該
  工具,工具開發(fā)盡量簡(jiǎn)單,一個(gè)工具只完成一個(gè)任務(wù),同時(shí)不要重復(fù)制造輪子。
  [java] view plain copy
  package d706; 
  /*
  * sql處理
  */ 
  public class Test_DB_Insert extends Thread{ 
  public static String SQLTEXT = null;  // 待處理的sql語(yǔ)句 
  private InputStream ins = null;       // 用于讀取配置文件  
  private Properties property = new Properties(); // 讀取數(shù)據(jù)庫(kù)配置文件 
  private String databaseType = null; // 數(shù)據(jù)庫(kù)連接類型 
  private String driver = null;       // 數(shù)據(jù)庫(kù)驅(qū)動(dòng) 
  private String url = null;          // 數(shù)據(jù)庫(kù)連接 
  private String uName = null;        // 數(shù)據(jù)庫(kù)登錄用戶名 
  private String pwd = null;          // 數(shù)據(jù)庫(kù)登錄用戶密碼 
  private  int numOfTestRecords;      // 插入數(shù)據(jù)條數(shù) 
  private  Connection con = null;     // 連接數(shù)據(jù)庫(kù) 
  private  PreparedStatement statement = null;  // 獲取數(shù)據(jù)庫(kù)操作對(duì)象 
  public  Test_DB_Insert(String sql){ 
  SQLTEXT = sql;                  // sql語(yǔ)句以參數(shù)的形式,在構(gòu)造實(shí)例的時(shí)候傳入 
  } 
  private void init(){   // 初始化配置文件 
  try{ 
  ins = new FileInputStream("./d706/dbconf.properties");  
  }catch(FileNotFoundException ffe){ 
  ffe.printStackTrace(); 
  } 
  try{ 
  property.load(ins);   // 
  }catch(IOException ie){ 
  ie.printStackTrace(); 
  } 
  databaseType = property.getProperty("databasetype"); // 獲取配置文件中設(shè)置的連接數(shù)據(jù)庫(kù)類型 
  if(databaseType.toUpperCase().equals("MYSQL")){      // 判斷連接數(shù)據(jù)庫(kù)類型 
  driver = property.getProperty("driver_mysql"); 
  url = property.getProperty("url_mysql"); 
  uName = property.getProperty("db_userName_mysql"); // 連接數(shù)據(jù)庫(kù)的用戶信息; 
  pwd = property.getProperty("db_pwd_mysql"); 
  }else if(databaseType.toLowerCase().equals("oracle")){ // 
  driver = property.getProperty("driver_oracle"); 
  url = property.getProperty("url_oracle"); 
  uName = property.getProperty("db_userName_oracle"); 
  pwd = property.getProperty("db_pwd_oracle"); 
  } 
  }                
  private  synchronized  void Insert_DB(){   
  try { 
  try { 
  Class.forName( driver );  // 注冊(cè)驅(qū)動(dòng); 
  }catch(ClassNotFoundException cf){ 
  cf.printStackTrace(); 
  } 
  con = DriverManager.getConnection(url,uName, pwd); // 獲取數(shù)據(jù)庫(kù)連接 
  con.setAutoCommit(false);  // 關(guān)閉事務(wù)自動(dòng)提交 
  SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:SS");  // 記錄執(zhí)行時(shí)間 
  TimeZone t = sdf.getTimeZone();   
  t.setRawOffset(0);   
  sdf.setTimeZone(t);   
  Long startTime = System.currentTimeMillis();   
  System.out.println("插入數(shù)據(jù)操作開始..."); 
  statement = con.prepareStatement(SQLTEXT); //創(chuàng)建數(shù)據(jù)庫(kù)操作對(duì)象 
  /*
  * "INSERT INTO TEST_DB(name,sex,nickname,test1,test2,test3,test4," +
  "test5,test6,test7,test8,test9,test10,test11,test12,test13,test14," +
  "test15,test16,test17,test18,test19,test20,test21,test22,test23," +
  "test24,test25,test26,test27,test28,test29,test30,test31,test32," +
  "test33,test34,test35,test36,test37,test38,test39,test40,test41," +
  "test42) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?," +
  "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
  */ 
  numOfTestRecords = 1000;                               //插入的測(cè)試數(shù)據(jù)量; 
  for(int i = 0; i<numOfTestRecords; i++) {              //循環(huán) 
  statement.setString(i + 1, "DBTest-" + i);  
  //statement.setString(2, "" + i%2);          //0表示男 1表示女  
  statement.addBatch();  // 把一個(gè)SQL命令加入命令列表   
  //statement.executeUpdate(); //執(zhí)行SQL; 
  } 
  statement.executeBatch(); //執(zhí)行批量更新 
  con.commit();//語(yǔ)句執(zhí)行完畢,提交事務(wù)                   
  //int[] ref = statement.executeBatch();                
  //if(ref[numOfTestRecords-1] == 0){System.out.println("插入數(shù)據(jù)操作完成");} // 
  System.out.println("插入數(shù)據(jù)操作完成"); 
  Long endTime = System.currentTimeMillis();   
  System.out.println("插入"+numOfTestRecords+"條數(shù)據(jù),"+"用時(shí)(時(shí):分:秒:毫秒)" +  
  sdf.format(new Date(endTime - startTime))); // 
  }catch(Exception e) {  
  System.out.println("異常: " + e.toString()); 
  e.printStackTrace();  
  }finally{ 
  if(statement != null){   // 關(guān)閉數(shù)據(jù)庫(kù)操作對(duì)象                        
  try{ 
  statement.close(); 
  }catch(SQLException se){ 
  se.printStackTrace(); 
  } 
  } 
  if(con != null){         // 關(guān)閉數(shù)據(jù)庫(kù)連接                      
  try{ 
  if(con.isClosed()){con.close();}   
  }catch(SQLException se){ 
  se.printStackTrace(); 
  } 
  } 
  }        
  } 
  @Override 
  public void run() {    // 類外調(diào)用  
  Test_DB_Insert ti = new Test_DB_Insert(SQLTEXT); // 構(gòu)造實(shí)例 
  ti.init();      // 初始化 
  ti.Insert_DB(); // 執(zhí)行插入數(shù)據(jù) 
  } 
  //  public static void main(String[] args){ 
  //                   
  //          Test_DB_Insert ti = new Test_DB_Insert(SQLTEXT); 
  //          ti.init();  //初始化 
  //          ti.Insert_DB();  //執(zhí)行插入數(shù)據(jù) 
  //  } 
  } 
  // 針對(duì)增刪查改,可放到一個(gè)SQL處理類(Test_DB_crud)中,判斷傳入的SQL字符串,然后交給對(duì)應(yīng)的方法去執(zhí)行并在控制臺(tái)輸出結(jié)果。 在Test_DB_Control類

上一頁(yè)12下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd