1、概述
使用Loadrunner對IBM MQ進行性能測試,須要用到java vuser以及java編碼知識。這次先介紹什麼是IBM MQ,而後java vuser的使用與配置細節,最後介紹IBM MQ的測試腳本。
2、IBM MQ介紹
IBM MQ(IBM Message Queue)是IBM的一款商業消息中間產品,適用於分佈式計算環境或異構系統之中。消息隊列技術是分佈式應用間交換信息的一種技術。消息隊列可駐留在內存或磁盤上,隊列存儲消息直到它們被應用程序讀走。
經過消息隊列應用程序可獨立地執行,它們不須要知道彼此的位或在繼續執行前不須要等待接收程序接收此消息。
對列管理器
隊列管理器是MQ系統中最上層的一個概念,由它爲咱們提供基於隊列的消息服務。
對列
隊列是消息的安全存放地,隊列存儲消息直到它被應用程序處理。
通道
通道是MQ系統中隊列管理器之間傳遞消息的管道,它是創建在物理的網絡鏈接之上的一個邏輯概念,也是MQ產品的精華。
在 MQ中,主要有三大類通道類型,即消息通道,MQI通道和Cluster通道。
消息通道是用於在MQ的服務器和服務器之間傳輸消息的,須要強調指出的是, 該通道是單向的,它又有發送(sender), 接收(receive), 請求者(requestor), 服務者(server)等不一樣類型,供用戶在不一樣狀況下使用。
MQI通道是MQ Client和MQ Server之間通信和傳輸消息用的,與消息通道不一樣,它的傳輸是雙向的。
羣集(Cluster)通道是位於同一個MQ 羣集內部的隊列管理器之間通信使用的。
消息
在MQ中,咱們把應用程序交由MQ傳輸的數據定義爲消息,咱們能夠定義消息的內容並對消息進行廣義的理解,好比:用戶的各類類型的數據文件,某個應用向其 它應用發出的處理請求等均可以做爲消息。消息有兩部分組成:消息描述符(Message Discription或Message Header),描述消息的特徵,如:消息的優先級、生命週期、消息Id等;消 息體(Message Body),即用戶數據部分。在MQ中,消息分爲兩種類型,非永久性(non-persistent)消息和永久性(persistent)消息,非永久 性消息是存儲在內存中的,它是爲了提升性能而設計的,當系統掉電或MQ隊列管理器從新啓動時,將不可恢復。當用戶對消息的可靠性要求不高,而側重系統的性 能表現時,能夠採用該種類型的消息,如:當發佈股票信息時,因爲股票信息是不斷更新的,咱們可能每若干秒就會發布一次,新的消息會不斷覆蓋舊的消息。永久 性消息是存儲在硬盤上,而且紀錄數據日誌的,它具備高可靠性,在網絡和系統發生故障等狀況下都能確保消息不丟、不重。
此外,在MQ中,還有邏輯消息和物理消息的概念。利用邏輯消息和物理消息,咱們能夠將大消息進行分段處理,也能夠將若干個自己完整的消息在應用邏輯上歸爲一組進行處理。
3、Loadrunner java vuser的使用與配置
準備html
loadrunner 11
jdk 1.6(32位)
com.ibm.mq.jar
connector.jar
com.ibm.mq.jmqi.jar
com.ibm.mq.headers.jar
com.ibm.mq.commonservices.jar
建立
打開loadrunner選擇新建Java Vuser,以下圖所示:
配置
開啓Run-time Setting,導入以前準備好的jar,以下圖所示:
配置Java VM,先選中紅框所示單選框,而後輸入本機所安裝JDK位置,以下圖所示:
4、測試腳本
如下爲MQ發送測試腳本,利用此腳本只用根據相應測試需求,調整註釋部分:
/*
* LoadRunner Java script. (Build: _build_number_)
*
* Script Desc
ription:
simple test harness to PUT messages on a MQ queue
*
*/
import lrapi.lr;
import com.ibm.mq.*;
import java.util.HashMap;
import java.util.Random;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Actions
{
// 隊列管理器
String queueMgrName = "QMCCPS01";
// 隊列名
String putQueueName = "CNAPS_BPH";
// 通道名
String channel = "SYSTEM.DEF.SVRCONN";
// 消息
String msgBody = "";
// ip 地址
String hostname = "10.40.2.16";
// 端口號
int port = 1601;
// 字符集
int CCSID = 819;
MQQueueManager queueMgr = null;
MQQueue getQueue = null;
MQQueue putQueue = null;
MQPutMessageOptions pmo = new MQPutMessageOptions();
MQGetMessageOptions gmo = new MQGetMessageOptions();
MQMessage requestMsg = new MQMessage();
MQMessage responseMsg = new MQMessage();
// ?????????
public int init() throws Throwable{
// Open a connection to the queue manager and the put/get queues
try {
// As values set in the MQEnvironment class take effect when the
// MQQueueManager constructor is called, you must set the values
// in the MQEnvironment class before you construct an MQQueueManager
// object.
MQEnvironment.hostname=hostname;
MQEnvironment.port=port;
MQEnvironment.CCSID =CCSID;
MQEnvironment.properties.put("transport", "MQSeries");
// MQEnvironment.channel = "SYSTEM.DEF.SVRCONN";
MQEnvironment.channel = channel;
queueMgr = new MQQueueManager(queueMgrName);
// Access the put/get queues. Note the open options used.
putQueue = queueMgr.accessQueue(putQueueName, 49);
// getQueue= queueMgr.accessQueue(getQueueName,
// MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_OUTPUT);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
public int action() throws Throwable{
// This is an XML message that will be put on the queue. Could do some
// fancy
// things with XML classes here if necessary.
// The message string can contain {parameters} if lr.eval_string() is
// used.
// Clear the message objects on each iteration.
requestMsg.clearMessage();
responseMsg.clearMessage();
//讀取報文內容,並利用replace函數參數化報文編號
String req = read("G:\\大額貸記來帳.xml");
String data_msg = "<data_msg>";
String msgBody = req.replace("<MsgId>2010101000000000</MsgId>", "<MsgId>20200117" + data_msg + "</MsgId>");
// Create a message object and put it on the request queue
try {
pmo.options = MQC.MQPMO_NEW_MSG_ID; // The queue manager replaces
// the contents of the MsgId
// field in MQMD with a new
// message identifier.
// should be put on this queue
requestMsg.report = MQC.MQRO_PASS_MSG_ID; // If a report or reply is
// generated as a result
// of this message, the
// MsgId of this message
// is copied to the
// MsgId of the report
// or reply message.
requestMsg.format = MQC.MQFMT_STRING; // Set message format. The
// application message data
// can be either an SBCS
// string (single-byte
// character set), or a DBCS
// string (double-byte
// character set).
// requestMsg.messageType=MQC.MQMT_REQUEST; // The message is one
// that requires a reply.
lr.start_transaction("大額貸記來帳");
requestMsg.writeString(msgBody); // message payload
MQMessage inMsg = new MQMessage();
inMsg.write(msgBody.getBytes("UTF-8"));
putQueue.put(inMsg,pmo);
lr.end_transaction("大額貸記來帳",lr.PASS );
} catch (Exception e) {
e.printStackTrace();
}
/***
* // Get the response message object from the response queue try {
* responseMsg.correlationId = requestMsg.messageId; // The Id to be
* matched against when getting a message from a queue
* gmo.matchOptions=MQC.MQMO_MATCH_CORREL_ID; // The message to be
* retrieved must have a correlation identifier that matches the value
* of the CorrelId field in the MsgDesc parameter of the MQGET call.
* gmo.options=MQC.MQGMO_WAIT; // The application waits until a suitable
* message arrives. gmo.waitInterval=60000; // timeout in ms
* getQueue.get(responseMsg, gmo);
*
* // Check the message content byte[] responseMsgData =
* responseMsg.readStringOfByteLength
* (responseMsg.getTotalMessageLength()).getBytes(); String msg = new
* String(responseMsgData); lr.output_message(msg); // for debugging.
* Disable this for a load test. // TODO: add your own message checking
* here using string functions. // I have found that extracting XML
* fields and comparing them (rather than // comparing the whole message
* body or substrings) is more resistant to change. // If no match is
* found, then lr.error_message() and lr.exit(). } catch(Exception e) {
* e.printStackTrace(); lr.error_message("Error receiving message.");
* lr.exit(lr.EXIT_VUSER, lr.FAIL); }
*
* lr.end_transaction("test_message", lr.AUTO);
*/
return 0;
}// end of action
// ???????
public int end() throws Throwable{
// Close all the connections
try {
putQueue.close();
// getQueue.close();
queueMgr.close();
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}// end of end
public static String read(String fileName){
String req = "";
FileInputStream in = null;
try {
in = new FileInputStream(fileName);
int len = in.available();
byte[] b = new byte[len];
in.read(b);
req = new String(b);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return req;
}
}