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

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

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