1. 程式人生 > >效能測試工具操作資料庫(九)-Loadrunner與MongoDB

效能測試工具操作資料庫(九)-Loadrunner與MongoDB

1、在loadrunner中新建指令碼(本文以LoadRunner11為例),要求選擇協議型別為Java->Java Vuser

2、在Run-time Settings設定JDK路徑,由於LoadRunner11不支援jdk1.8,本次測試是拷貝了一份低版本的JDK1.6,所以路徑選擇固定路徑模式,如下所示:


3、上網下載一份MongoDB的JAR包(注意以下指令碼是在版本為2.*的JAR包上除錯通過,不保證在3.*或更高版本中能夠執行),下載地址:http://central.maven.org/maven2/org/mongodb/mongo-java-driver/2.13.3/mongo-java-driver-2.13.3.jar,放到include目錄下,並在Run-time Settings中配置Classpath


4、在Java Vuser指令碼中編寫MongoDB的增、刪、改、查操作:

/*
 * LoadRunner Java script. (Build: _build_number_)
 * 
 * Script Description:                     
 */
import lrapi.lr;
import java.net.UnknownHostException; 
import java.util.ArrayList;
import java.util.List;  
  
import org.bson.types.ObjectId;  
  
import com.mongodb.BasicDBObject;  
import com.mongodb.DB;  
import com.mongodb.DBCollection;  
import com.mongodb.DBCursor;  
import com.mongodb.DBObject;  
import com.mongodb.Mongo;  
import com.mongodb.MongoException;

public class Actions
{
        //1.建立一個Mongo的資料庫連線物件  
	static Mongo conn = null;  
	//2.建立相關資料庫的連線  
	static DB db = null;
        /** 
	* 為相應的集合新增資料 
	* @param dbs 
	* @param collName 
	*/  
	public void insert(DBObject dbs,String collName){  
	    //1.得到集合  
	    DBCollection coll = db.getCollection(collName);  
	    //2.插入操作  
	    coll.insert(dbs);  
	}  
	/** 
	* 為集合批量插入資料 
	* @param dbses 
	* @param collName 
	*/  
	public void insertBatch(List<DBObject> dbList,String collName){  
	    //1.得到集合  
	    DBCollection coll = db.getCollection(collName);  
	    //2.插入操作  
	    coll.insert(dbList);  
	}  
	/** 
	* 根據id刪除資料 
	* @param id 
	* @param collName 
	* @return 返回影響的資料條數 
	*/  
	public int deleteById(String id,String collName){  
	    //1.得到集合  
	    DBCollection coll = db.getCollection(collName);  
	    DBObject dbs = new BasicDBObject("_id", new ObjectId(id));  
	    int count = coll.remove(dbs).getN();  
	    return count;  
	}  
	/** 
	* 根據條件刪除資料 
	* @param id 
	* @param collName 
	* @return 返回影響的資料條數 
	*/   
	public int deleteByDbs(DBObject dbs,String collName){  
	    //1.得到集合  
	    DBCollection coll = db.getCollection(collName);  
	    int count = coll.remove(dbs).getN();  
	    return count;  
	}  
	/** 
	 * 更新資料 
	* @param find 查詢器 
	* @param update 更新器 
        * @param upsert 更新或插入(設為ture,若所更新的資料沒有則插入)
	* @param multi 是否批量更新 
	* @param collName 集合名稱 
	* @return 返回影響的資料條數 
	*/  
	public int update(DBObject find,  
        	DBObject update,  
       		boolean upsert,  
       		boolean multi,  
        	String collName){  
	    		//1.得到集合  
	    		DBCollection coll = db.getCollection(collName);  
	    		int count = coll.update(find, update, upsert, multi).getN();  
	    		return count;  
		}
        /** 
	* 查詢器(分頁) 
	* @param ref 
	* @param keys 
	* @param start 
	* @param limit 
	* @return 
	*/  
	public DBCursor find(DBObject ref,   
        	DBObject keys,  
        	int start,  
        	int limit,  
        	String collName){  
			DBCursor cur = find(ref, keys, collName);  
			return cur.limit(limit).skip(start);  
		}  
	/** 
	* 查詢器(不分頁) 
	* @param ref 
	* @param keys 
	* @param start 
	* @param limit 
	* @param collName 
	* @return 
	*/  
	public DBCursor find(DBObject ref,  
        	DBObject keys,  
        	String collName){  
			//1.得到集合  
			DBCollection coll = db.getCollection(collName);  
			DBCursor cur = coll.find(ref, keys);  
			return cur;  
		}

	public int init() throws Throwable {
		conn = new Mongo("172.16.1.238",27017); 
		db = conn.getDB("test");
		return 0;
	}//end of init

	public int action() throws Throwable {
		//DBCollection coll = db.getCollection("testCollection");

	    lr.start_transaction("插入操作");
		List<DBObject> dbList = new ArrayList<DBObject>();
		BasicDBObject doc = new BasicDBObject("DataName", "MongoDB-<RadNum><RadNum2>").
                              append("DataType", 1).
                              append("remark", "From Loadrunner").
                              append("Date", new BasicDBObject("InsertTime", "<getTime>").append("UpdateTime", null));
                              dbList.add(doc);

		BasicDBObject doc2 = new BasicDBObject();  
			      doc2.put("name", "小張");  
			      doc2.put("age", 25);  
			      doc2.put("address", "江蘇蘇州");  
			      dbList.add(doc2); 
		//2.插入操作  
		//coll.insert(dbList);
		insertBatch(dbList,"testCollection");
	    lr.end_transaction("插入操作", lr.AUTO);

	    lr.start_transaction("刪除操作");
		//BasicDBObject dbs = new BasicDBObject("DataName", "MongoDB-1964905.821");
		BasicDBObject dbs = new BasicDBObject();
		dbs.put("DataName", "MongoDB-1964905.821");
		int dels=deleteByDbs(dbs,"testCollection");
		//System.out.println("刪除的條數:"+dels);
		lr.log_message("刪除的條數:"+dels);
	    lr.end_transaction("刪除操作", lr.AUTO);

	    lr.start_transaction("更新操作");
		DBObject updateCondition=new BasicDBObject();  
          
		//where name='小張'  
		updateCondition.put("name", "小張");  
          
		DBObject updatedValue=new BasicDBObject();  
		updatedValue.put("age", 28);  
		updatedValue.put("address", "吉林長春");  
          
		DBObject updateSetValue=new BasicDBObject("$set",updatedValue);
		/** 
		* update insert_test set age=28 and address="吉林長春" where name="小張"
		* updateCondition:更新條件 
		* updateSetValue:設定的新值 
		*/
		int upds=update(updateCondition, updateSetValue, true, true,"testCollection");
		lr.log_message("更新的條數:"+upds);
	    lr.end_transaction("更新操作", lr.AUTO);

	    lr.start_transaction("查詢操作");
		DBObject ref=new BasicDBObject();  
          
		//1、查詢出年齡大於25歲並且小於65歲     
		ref.put("age", new BasicDBObject("$gte",25));  
		ref.put("age", new BasicDBObject("$lte",65));  
          
		DBCursor cursor=find(ref,null,1,4,"testCollection");//查詢獲取第2條開始的4條記錄
                while (cursor.hasNext()) {  
		    DBObject object = cursor.next();  
		    System.out.print(object.get("name")+"-->");  
		    System.out.print(object.get("age")+"-->");  
		    System.out.println(object.get("address"));  
		}

		//2、查詢出testCollection集合中的name和age
                DBObject keys = new BasicDBObject();  
		keys.put("_id", false);  
		keys.put("name", true);  
		keys.put("age", true);  
		DBCursor cursor2 = find(null, keys, "testCollection"); 
		while (cursor2.hasNext()) {  
		    DBObject object = cursor2.next();  
		    System.out.println(object.get("name"));  
		} 

	    lr.end_transaction("查詢操作", lr.AUTO);

		return 0;
	}//end of action

	public int end() throws Throwable {
		conn.close();//關閉資料庫連線
		db=null;
		conn=null;//回收資源
		return 0;
	}//end of end
}

5、執行指令碼,輸出正確的操作結果

注意:對於loadrnner指令碼要通過Load Generators進行分散式測試時,請確保各負載壓力機的JDK和Classpath路徑都能夠正確呼叫(需要保持相同的路徑)。

另外需要說明的是:2.10.0版本開始引入了MongoClient類,同時在其API中也說明了Mongo類會在將來的版本中被MongoClient替換(Note: This class has been superseded by MongoClient, and may be deprecated in a future release.)。以上MongoDB連線用的還是Mongo類,所以程式碼僅供大家參考而已,實際專案測試還是建議採用MongoClient,否則在高併發情況下可能容易出現效能問題或其他異常問題。

由於出於執行緒安全等考慮,MongoDB Java從3.0開始已經打算廢棄DB開頭的類的使用,所以整體呼叫上有了較大的區別。以下提供了在3.4.2版本中測試通過的程式碼,以供大家參考(相當於對上面測試程式碼的重構)

/*
 * LoadRunner Java script. (Build: _build_number_)
 * 
 * Script Description: 
 *                     
 */
import java.util.ArrayList;
import java.util.List;
import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import org.bson.types.ObjectId;

import lrapi.lr;

public class Actions
{
    //1.建立一個Mongo的資料庫連線物件   
    static MongoClient mongoClient = null;
    //2.建立相關資料庫的連線  
    static MongoDatabase mongoDatabase = null;
    //3.連線集合
    static MongoCollection<Document> mongoCollection = null;

    /*連線資料庫*/
    public void connection(String connIP,int port,String dataName){
        //連線到服務
        mongoClient = new MongoClient(connIP,port);
        //連線到資料庫  
        mongoDatabase = mongoClient.getDatabase(dataName);
            
	}
  /** 
	* 為相應的集合新增資料 
	* @param doc 
	* @param collName 
	*/  
	public void insert(Document doc,String collName){ 
			try { 
                //獲取集合 引數為“集合名稱”  
                mongoCollection = mongoDatabase.getCollection(collName); 
                List<Document> documents = new ArrayList<Document>();  
                documents.add(doc);
                //2.插入操作  
                mongoCollection.insertMany(documents);
			} catch (Exception e) {  
                System.err.println( e.getClass().getName() + ": " + e.getMessage() );  
			}
	}
	/*批量新增資料*/
	public void insertBatch(List<Document> docs,String collName){
       try { 
                //獲取集合 引數為“集合名稱”  
            mongoCollection = mongoDatabase.getCollection(collName); 
                //2.批量插入操作  
            mongoCollection.insertMany(docs);
       } catch (Exception e) {  
            System.err.println( e.getClass().getName() + ": " + e.getMessage() );  
      }
	}
	/** 
	* 根據資料條件刪除資料
  * @param key
  * @param keyValue
	* @param collName 
	*/  
	public void deleteByDbs(String key,Object keyValue,String collName){
      try { 
            //獲取集合 引數為“集合名稱”  
            mongoCollection = mongoDatabase.getCollection(collName); 
            //long cnt = mongoCollection.count(Filters.eq(key, keyValue));//統計刪除的記錄數
            //System.out.println("刪除的記錄數:"+cnt);
            //刪除所有符合條件的文件  
           	mongoCollection.deleteMany(Filters.eq(key, keyValue));
						//mongoCollection.deleteMany(Filters.ne("",""));//清空測試資料
            //檢索檢視結果  
            /*FindIterable<Document> findIterable = mongoCollection.find();  
            MongoCursor<Document> mongoCursor = findIterable.iterator();  
            while(mongoCursor.hasNext()){
                System.out.println(mongoCursor.next());  
            }*/
       } catch (Exception e) {
            System.err.println( e.getClass().getName() + ": " + e.getMessage() );  
       }
              
	}  
	
	/** 
	* 更新資料 
  * @param key 過濾引數
  * @param value 過濾引數對應值
	* @param update 更新器 
	* @param collName 集合名稱 
	*/
	public void update(String key,Object value,
                        Document update,    
                        String collName){  
       try {
                //1.得到集合  
                mongoCollection = mongoDatabase.getCollection(collName);  
                //更新文件將文件中key=value的文件修改
                mongoCollection.updateMany(Filters.eq(key, value), update);  
                //檢索檢視結果  
                /*FindIterable<Document> findIterable = mongoCollection.find();  
                MongoCursor<Document> mongoCursor = findIterable.iterator();  
                while(mongoCursor.hasNext()){  
                    System.out.println(mongoCursor.next());  
                }*/
                //long cnt = mongoCollection.count(Filters.eq(key, value));//統計更新的記錄數
                //System.out.println("更新的記錄數:"+cnt);
        } catch (Exception e) {  
                System.err.println( e.getClass().getName() + ": " + e.getMessage() );  
        }
	}
	/** 
	* 查詢器 
	* @param ref 
	* @param keys 
	* @param start 
	* @param limit 
	* @return 
	*/  
	public void find(Document ref,   
            Document keys,  
            int start,  
            int limit,  
            String collName){ 
     try {
         	//1.得到集合  
         	mongoCollection = mongoDatabase.getCollection(collName);     
         	//按id倒序排,跳過前m條(0-m),返回n條。
         	FindIterable<Document> findIterable = mongoCollection.find(ref).sort(new Document("_id",-1)).skip(start).limit(limit);
         	//檢索檢視結果
         	MongoCursor<Document> mongoCursor = findIterable.iterator();
         	while(mongoCursor.hasNext()){
                System.out.println(mongoCursor.next());
         	} 
      } catch (Exception e) {  
          System.err.println( e.getClass().getName() + ": " + e.getMessage() );  
      } 
	}  

	public int init() throws Throwable {
    connection("172.16.1.157",8096,"test10");
		return 0;
	}//end of init

	public int action() throws Throwable {
	    int radNum=(int)(Math.random()*100);//隨機數,判斷刪除和更新
	    String getTimes="<getTime>";//插入資料的時間
	    lr.start_transaction("插入資料");
            List<Document> documentList = new ArrayList<Document>();  
            Document document1 = new Document("DataName", "MongoDB-<RadNum><RadNum2>").  
                    append("DataType", 1).  
                    append("remark", "From Loadrunner").
                    append("Date", new Document("InsertTime", getTimes).append("UpdateTime", null));
            documentList.add(document1);

            Document document2 = new Document();  
            document2.put("name", "<BJX><XM>");  
            document2.put("age", Integer.parseInt("<ages>"));  
            document2.put("address", "<DZ>");  
            documentList.add(document2); 
            //批量插入操作
            insertBatch(documentList,"test");
	    lr.end_transaction("插入資料", lr.AUTO);
         	/*以新插入資料id作為刪除和更新的條件(因為id已建立了索引和分片,能保證操作速度)*/
         	ObjectId id_1 = (ObjectId)document1.get( "_id" );//第一條插入資料id
         	ObjectId id_2 = (ObjectId)document2.get( "_id" );//第二條插入資料id           

         	//System.out.println("隨機數:"+radNum);
         	if(radNum<50){/*針對插入的兩條資料,隨機刪除其中一條*/
					lr.start_transaction("刪除操作");
		    			//String delKey="DataName";
		    			//String delKeyValue="MongoDB-<RadNum><RadNum2>";
		    			String delKey="_id";
		    			ObjectId delKeyValue=id_1;
		    			deleteByDbs(delKey,delKeyValue,"test");
					lr.end_transaction("刪除操作", lr.AUTO);
         	}else{
					lr.start_transaction("刪除操作");
		    			//String delKey="name";
		    			//String delKeyValue="<BJX><XM>";
		    			String delKey="_id";
		    			ObjectId delKeyValue=id_2;
		    			deleteByDbs(delKey,delKeyValue,"test");
					lr.end_transaction("刪除操作", lr.AUTO);
         	}

	    lr.start_transaction("更新操作");
				String updKey=null;
				ObjectId updKeyValue=null;
				Document updatedValue=null;
				if(radNum>=50){
		    		//updKey="DataName";
		    		//updKeyValue="MongoDB-<RadNum><RadNum2>";
		    		updKey="_id";
		    		updKeyValue=id_1;   
		    		updatedValue=new Document();  
		    		updatedValue.put("DataType", 2);  
		    		updatedValue.put("Date", new Document("InsertTime", getTimes).append("UpdateTime", "<getTime>"));
				}else{
		    		//where name='小張'
		    		//updKey="name";
		    		//updKeyValue="<BJX><XM>";
		    		updKey="_id";
		    		updKeyValue=id_2;
          
		    		updatedValue=new Document();  
		    		updatedValue.put("age", Integer.parseInt("<ages>"));  
		    		updatedValue.put("address", "<DZ>-update");  
				}
				Document updateSetValue=new Document("$set",updatedValue);
				update(updKey, updKeyValue, updateSetValue, "test");
	    lr.end_transaction("更新操作", lr.AUTO);

	    lr.start_transaction("查詢操作");
				Document ref=new Document();  
          
				//1、查詢出年齡大於25歲並且小於65歲     
				ref.put("age", new Document("$gte",25));  
				ref.put("age", new Document("$lte",65));  
                  				find(ref,null,Integer.parseInt("<i>"),Integer.parseInt("<n>"),"test");//查詢獲取第i條開始的n條記錄
		
	    lr.end_transaction("查詢操作", lr.AUTO);

				//統計資料庫記錄數  
				/*mongoCollection = mongoDatabase.getCollection("test");
			long cnt1 = mongoCollection.count(Filters.eq("remark", "From Loadrunner"));//統計更新的記錄數
			lr.log_message("統計資料1記錄數:"+cnt1);
			long cnt2 = mongoCollection.count(Filters.eq("age", new Document("$gte",0)));//統計更新的記錄數
			lr.log_message("統計資料2記錄數:"+cnt2);*/

			return 0;
	}//end of action

	public int end() throws Throwable {
			mongoClient.close();
			mongoDatabase=null;
			mongoClient=null;
	    return 0;
	}//end of end
	
}