性能測試分享—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 { return 0; }//end of action //在end方法里面編寫最后要執行的方法,如釋放資源,沒有可以不寫。 public int end() throws Throwable { return 0; }//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;
}
調整為
events {
worker_connections 65535;
}
最后附上我寫的信用卡支付的腳本:
/* * LoadRunner Java script. (Build: _build_number_) * * Script Description: * */ import lrapi.lr; 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 class Actions { 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(); public int init() throws Throwable { 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); } catch (Exception e) { e.printStackTrace(); } client.shutdown(); return 0; }//end of init public int action() throws Throwable { 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); try { 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(); System.out.println(respStr); String result = AES.decryptFromBase64(respStr, encryptkey); System.out.println(result); method.releaseConnection(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace();} lr.end_transaction("pay", lr.AUTO); return 0; }//end of action public int end() throws Throwable { return 0; }//end of end } |
posted on 2014-01-03 13:42 順其自然EVO 閱讀(425) 評論(1) 編輯 收藏 所屬分類: loadrunner