效能測試工具操作資料庫(九)-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
}