天天看點

性能測試分享—LoadRunner篇

  loadrunner性能測試工具使用:

  1、建立腳本,選擇java vuser協定。初步結構是

import lrapi.lr;

public class actions

{

//在init方法裡面編寫一個虛拟使用者循環隻執行一次的方法,如可以把協商寫在裡面,就可以達到每個使用者協商一次之後,就不再協商的效果

public int init() throws throwable {

return 0;

}//end of init

//在aciton方法裡面編寫需要循環并發的業務方法,如交易的方法,在run_time settings中設定循環的次數。

public int action() throws throwable {

}//end of action

//在end方法裡面編寫最後要執行的方法,如釋放資源,沒有可以不寫。

public int end() throws throwable {

}//end of end

}

  2、在初始代碼的基礎上繼續編寫業務方法。需要注意的是:

  1)把隻需要建立一次對象的語句如:random rd = new random();放在init,aciton,end方法之外,可以避免在循環中建立很多的對象。但是需要注意的是如果是建立http請求的對象是需要反複建立的,不能單提出來,否則執行一次之後,該連接配接被釋放了,而沒有建立新的連接配接,第二次就執行不下去了。

  2)腳本編寫完之後,将該腳本所有import的類的jar包放在一個檔案夾下,點選run time settings的classpath,把所有jar包都添加進去。

  3)運作腳本,看看能不能成功執行,按照錯誤提示調試腳本。

  4)接下來,可以把需要變化的值進行參數化。如商戶名和aeskey。選中值,右鍵選擇replace with a parameter,在parameter list功能裡添加需要用到的商戶和aeskey的值,将商戶參數的循環方式select next row選擇unqie,update value on選擇once,表示為個商戶隻取唯一的值。aeskey的select next row選擇same line as merchant。

  5)接下來插入事物,把需要計算業務時間的代碼前後都插入事物函數,如lr.start_transaction("pay");lr.end_transaction("pay", lr.auto);如果想更加詳細的知道每一步操作的時間,可以多插入一些事物,如加密,解密,擷取傳回值等步驟均插入事物函數。

  6)如果需要并發執行,還需要插入集合點函數lr.rendezvous("pay");這樣在場景裡并發執行的時候,所有的虛拟使用者會等到都準備好之後在一個時間點執行。

  7)接下來就是在場景裡執行了。點選tools---create controller scenario。進入場景。并發10個使用者執行5分鐘。同時監控tomcat的日志。

  在并發的情況下,出現了一些問題,下面針對這些問題給出解決方案。

  遇到的問題1、在并發執行1分鐘後,開始有報錯,主要的報錯是解密失敗,同時tomcat挂了,不能在接受新的請求。

  找到問題根源:通過監控tomcat日志,發現後期有很多的報錯日志是檔案打開過多。

  嚴重: socket accept failed java.net.socketexception: 打開的檔案過多 at java.net.plainsocketimpl.socketaccept(native method) at java.net.plainsocketimpl.accept(plainsocketimpl.java:408) at java.net.serversocket.implaccept(serversocket.java:462) at java.net.serversocket.accept(serversocket.java:430) at org.apache.tomcat.util.net.defaultserversocketfactory.acceptsocket(defaultserversocketfactory.java:61) at org.apache.tomcat.util.net.jioendpoint$acceptor.run(jioendpoint.java:352) at java.lang.thread.run(thread.java:662) 2013-5-16 11:38:46 org.apache.tomcat.util.net.jioendpoint$acceptor run 2013-05-16 11:38:44,974 info [defaultrequestdirector.java:586] - i/o exception (java.net.socketexception) caught when connecting to the target host: 打開的檔案過多 2013-05-16 11:38:44,974 error [creditpay.java:167] - 信用卡支付失敗 com.yibao.payapi.client.requestapiexception: 請求服務未正常傳回[statuscode:404, text:<html><head><title>apache tomcat/6.0.29 -

  解決方案:由于建立socket會占用一個系統句柄,效果類似于打開了一個檔案。linux預設的最大檔案打開個數是1024(可能不同核心版本不一樣),是以如果并發太多連接配接時就會報錯。需要修改檔案打開數設定。

  目前設定最大打開檔案數可以通過如下指令檢視。    ulimit -n

  這個數字說明了一個普通使用者能夠在一個單獨會話中所能打開最大的檔案數目。注意。如果是root,以下操作不能使ulimit -n的輸出增加。因為使用者root使用者不受這個ulimit限制。隻有普通使用者才會受這個限制。

  為了提高最大打開檔案數到預設值1024以上, 需要在系統上修改2個地方。 在這個案例中, 我們将最大打開檔案數增加到為65535(系統部給出的建議)。 所有的步驟需要root使用者操作。

  1、/etc/pam.d/login 添加 session required     /lib/security/pam_limits.so

  2. 按照最大打開檔案數量的需求設定系統, 并且通過檢查/proc/sys/fs/file-max檔案來确認最大打開檔案數已經被正确設定。 echo 65535 > /proc/sys/fs/file-max

  3、在/etc/security/limits.conf檔案中設定最大打開檔案數,添加2行内容:

  * soft nofile 4096 * hard nofile 4096

  解釋:下面是一行提示

  #<domain>      <type>  <item>         <value>添加如下這行。 * - nofile 2048 這行設定了每個使用者的預設打開檔案數為2048。 注意"nofile"項有兩個可能的限制措施。 就是<type>項下的hard和soft。 要使修改過得最大打開檔案數生效,必須對這兩種限制進行設定。 如果使用"-"字元設定<type>, 則hard和soft設定會同時被設定。

  硬限制表明soft限制中所能設定的最大值。 soft限制指的是目前系統生效的設定值。 hard限制值可以被普通使用者降低。但是不能增加。 soft限制不能設定的比hard限制更高。 隻有root使用者才能夠增加hard限制值。

  遇到的問題2:在虛拟使用者少的時候并發沒有再出現檔案打開過多的錯誤,在并發量達到30,運作時間達到3分鐘的時候,有報錯:http-500

  找到問題根源:通過檢視tomcat和程式的日志,看到有大量的http-500的錯誤,是nginx已經拒絕了請求。

  解決方案:修改nginx配置檔案

  vi /etc/nginx/nginx.conf

  events {

  worker_connections 1024;

  }

  調整為

  worker_connections 65535;

 最後附上我寫的信用卡支付的腳本:

/*

* loadrunner java script. (build: _build_number_)

*

* script description:

*/

import http.httpclient4;

import http.httpparameter;

import http.httpresp;

import http.jsonutil;

import http.testcredit;

import org.apache.commons.httpclient.httpclient;

import org.apache.commons.httpclient.httpexception;

import org.apache.commons.httpclient.methods.postmethod;

import java.util.random;

import java.util.date;

import java.text.simpledateformat;

import java.util.calendar;

import com.yeepay.g3.utils.common.encrypt.aes;

import com.yibao.utils.des3.rsa_encrypt;

public  string aes;

date d = new date();

testcredit tc = new testcredit();

simpledateformat format = new simpledateformat("yyyy-mm-dd hh:mm:ss");

httpparameter parameter = new httpparameter();

string url = "http://xxxxx/xxxxx/consult";

httpclient4 client =httpclient4.createdefault();

string data = "";

calendar now = calendar.getinstance();

now.settime(d);

string dateline=format.format(now.gettime());

system.out.println(dateline);

date date = format.parse(dateline);

string dates=date.gettime()/1000+"";

system.out.println(dates);

try {

data = aes.encrypttobase64(dates, "<aes>");

} catch (exception e) {

e.printstacktrace();

parameter.add("data", data);

parameter.add("merchantaccount", "<merchant>");

httpresp resp = new httpresp();

try{

resp=client.dopost(url, parameter, "utf-8");

string respstr= resp.gettext("utf-8");

system.out.println(respstr);

aes=aes.decryptfrombase64(respstr, "<aes>");

system.out.println("aes="+aes);

client.shutdown();

stringbuilder sb = new stringbuilder("");

random rd = new random();

for(int i=1;i<=6;i++){

int sr=rd.nextint(9);

sb.append(string.valueof(sr));

string key=sb.tostring();

int rds=rd.nextint(999999);

lr.start_transaction("pay");

lr.rendezvous("pay");

httpclient client = new httpclient();

postmethod method = new postmethod("http://xxxxxxxx/xxxxxxx/api/bankcard/credit/pay");

system.out.println(aes);

string public_key=aes;

system.out.println("public_key"+public_key);

string encryptkey = "0123456789"+key;

string merchantaccount = "<merchant>";

//民生

string cardno = "6xxxxxxxxxxxxxx";

string validthru = "xxxx";

string cvv2 = "xxx";

string phone = "13466745431";

string orderid = rds+"334234223"+key;

system.out.println(orderid);

integer transtime = (int)(system.currenttimemillis()/1000);

integer currency = 156;

string  amount = "50";

string productcatalog = "1";

string productname = "123";

string productdesc = "小丸子";

string userip = "123.45.45.45";

string identityid = "a";

integer identitytype = 6;

string other = "eeee";

string data = "{\"merchantaccount\":\"" + merchantaccount

+"\",\"cardno\":\"" + cardno

+ "\",\"validthru\":\"" + validthru

+ "\",\"cvv2\":\"" + cvv2

+ "\",\"phone\":\"" + phone

+ "\",\"orderid\":\"" + orderid

+ "\",\"transtime\":" + transtime

+ ",\"currency\":" + currency

+ ",\"amount\":" + amount

+ ",\"productcatalog\":\"" + productcatalog

+ "\",\"productname\":\"" + productname

+ "\",\"productdesc\":\"" + productdesc

+ "\",\"userip\":\"" + userip

+ "\",\"identityid\":\"" + identityid

+ "\",\"identitytype\":" + identitytype

+ ",\"other\":\"" + other + "\"}";

data = aes.encrypttobase64(data, encryptkey);

method.setparameter("merchantaccount", merchantaccount);

method.setparameter("data", data);

method.setparameter("encryptkey", rsa_encrypt.encrypt(encryptkey, public_key));

client.executemethod(method);

system.out.println(method.getstatusline());

string respstr = method.getresponsebodyasstring();

string result = aes.decryptfrombase64(respstr, encryptkey);

system.out.println(result);

method.releaseconnection();

// todo auto-generated catch block

e.printstacktrace();}

lr.end_transaction("pay", lr.auto);

最新内容請見作者的github頁:http://qaseven.github.io/