基於LoadRunner的UDP和TCP服務性能測試


背景

  最近項目要做性能測試,要出要一份性能報告,讓我出一個有關Tcp和Udp的功能模塊的測試,流程大概是這樣,先走TCP協議協商一下會話,協商成功后走Udp收發數據。

  

  有點簡單啊,自己寫個功能模塊測一下,然后把結果展示出來就ok了。

  然而想法很美好,現實有點殘酷。idea瞬間被pass掉,理由就是自己寫的測試模塊木有說服力。

  

  要用專業的測試工具來搞,才有說服力。作為一名開發,用測試工具是不可能的,就算餓死也不會用!!!

   

  最后還是學了一下LoadRunner,在歷經一番坎坷摸索之后,出了個測試腳本。不得不說,LR真的挺好用的。(PS:真香現場)

       不說廢話了,在網上找了一下使用LR測試TCP和UDP的腳本,資料有點難找,大多都是簡單概況一下。(讓我一個LR初手,搞不定啊),最后在自己一番摸索之下,把過程整理一下,要有啥不好的地方,還請多指教一下。

准備工作

  • LoadRunner 環境,這個大家自行百度,教程太多我就不詳說了
  • 數據包,客戶端進行TCP協商的數據包,使用udp發送的數據包(用wireshark抓取)
  • LR的測試腳本

編寫測試腳本

  使用LR測試TCP和UDP要使用LR中Windows sockets協議,它可以模擬tcp/ip協議和服務器進行數據交互,這樣便可以模擬終端來進行性能測試了。首先打開LR Virtual User Generator選擇創建腳本。

                                              圖:創建腳本

  選擇創建windows sockets協議的腳本。

                圖:選擇socket協議

    接着會出來一個錄制選項框,在應用類型里有兩種選擇,一種是win32的應用,一種是瀏網絡應用,選擇后可以開始錄制腳本,會啟用對應的應用,根據操作錄制腳本。

                                                                                                         圖:初始化參數

   我這邊使用網絡應用,輸入要測試服務的URL,選擇對應的action,然后點擊ok就可以開始錄制。

   這里可以選擇的活動對應有三種

  • vuser_init:創建虛擬用戶初始化時做的事情, 比如要測試業務某個具體業務操作環節時,可以先把系統用戶登錄的寫在init中。
  • action:       用戶操作的事件,即需要測試業務操作點。
  • vuser_end:虛擬用戶退出的時候做到操作,如關閉socket等。

  不過錄制腳本這個功能生成的測試腳本有的時候不符合我們的預期,還是要自己修改,所以我這里隨便錄制了一下,然后重寫腳本。

       圖:結束錄制

  點擊結束錄制,會生成腳本,如下圖,然后我們就可以自己修改腳本了。

 

最后就是最關鍵的地方了,根據具體業務流程來編寫測試腳本,我這里總體業務流程大致如下

編寫vuser_init

  我這里由於要協商會話,所以在初始化時需要發送兩次請求和接受兩次請求,腳本如下

vuser_init()
{
    char*recvbuf;
    int recvlen=0;
    int rc=0;

    lrs_startup(257);
    //設定開始事務
    lr_start_transaction("Trans_Session");
    lr_start_transaction("Conn_TCP");
    //創建socket
    rc=lrs_create_socket("socket0","TCP","LocalHost=0","RemoteHost=127.0.0.1:8888",LrsLastArg);
    //判斷套接字創建是否成功
    if(rc!=0){
      lr_end_transaction("Conn_TCP",LR_FAIL);
      lr_end_transaction("Trans_Session",LR_FAIL);
    return 0;
    }
    lr_end_transaction("Conn_TCP",LR_PASS);  //判斷socket是否鏈接成功的事務,0表示創建成功  

    lrs_send("socket0","senCreateReqBuf",LrsLastArg); //發送安全會話建立請求,senCreateReq為在data.ws中定義的發送變量  
    lrs_receive("socket0","senCreateRspBuf",LrsLastArg); //接收消息,存放在senCreateReq中,senCreateReq是在data.ws中定義的接收數組,注意數組長度一定要大於等於實際接收長度  

    lrs_get_last_received_buffer("socket0",&recvbuf,&recvlen);//把Socket最后接收的字節數組,長度放在recvlen中,內容放在recvbuf中  

    if(recvlen<100) {
       lr_end_transaction("Trans_Session",LR_FAIL);
    }

    lrs_send("socket0","authReqBuf",LrsLastArg); //發送authRsp,authRsp為在data.ws中定義的發送變量  
    lrs_receive("socket0","authRspBuf",LrsLastArg); //接收消息,存放在authRep中,authRep是在data.ws中定義的接收數組,注意數組長度一定要大於等於實際接收長度 

    lrs_get_last_received_buffer("socket0",&recvbuf,&recvlen);//把Socket最后接收的字節數組,長度放在recvlen中,內容放在recvbuf中  

    if(recvlen>60)
      lr_end_transaction("Trans_Session",LR_PASS);
    else
      lr_end_transaction("Trans_Session",LR_FAIL);
    return 0;

}
   1. 首選創建相關測試的事務,在性能測試中這個可以作為測試用例通過的依據lr_start_transaction與lr_end_transaction 為使用最多的事物創造組合函數,lr_start_transaction為事物開始函數,lr_end_transaction為事物結束函數,並負責記錄事物的運行時間. 
語法格式如下:
  • int lr_start_transaction (const char * transaction_name);
  • int lr_end_transaction (const char * transaction_name,int status);
 其中transacton為事物名稱,status為事物的結束狀態,共有LR_PASS(通過)、LR_FAIL(失敗)、LR_AUTO(自動)、 LR_STOP(暫停),其中LR_PASS默認的是LR_PASS,可以在事物結束前通過lr_set_transaction_status進行修改。如果在lr_end_transaction中沒有指定結束事物狀態是LR_AUTO,而是明確制定為LR_PASS、LR_FAIL、 LR_STOP其中的其中,則事物將以最后制定狀態來結束。需要注意,事物開始沒有lr_end_transaction沒有結束的時候,不能用相同的事 物名稱,除非這個事物已經通過lr_end_transaction結束。
2. 接着創建socket,初始化套接字,使用的函數如下
  • int lrs_create_socket("socket0","TCP","LocalHost=0","RemoteHost=127.0.0.1:8888",LrsLastArg);

參數分別是:socket名稱、協議類型(TCP或UDP)、鏈接類型(遠程鏈接:RemoteHost、本地:LocalHost、或者本地監聽)、LrsLastArg 參數結束標記,創建成功返回0。

      3. 創建完套接字后,判斷時候成功,若是失敗將對應的事務狀態修改為LR_FAIL。

      4.通過socket發送數據,lrs_send("socket0","senCreateReqBuf",LrsLastArg); 這里senCreateReqBuf為待發送的數據,數據存在data.ws文件中


        send 后面填的是待發送數據buf的名稱,接着再跟上待發送數據的長度 ,待發送buf在LR中我這邊是以16進制發送,按照LR的規則需要在16進制值前中加上\x,很明顯構造這個數據還是麻煩的很。所以這里提供一個比較方便的方式。

  

        我們可以從wireshark中直接抓取對應格式的數據,選擇需要的數據,右鍵復制,選擇轉義字符串,就可以了,最后將復制的數據放在data.ws中就可以了。

5.接收響應數據,判斷響應數據是否正確,我這里根據長度來判斷。

編寫Action

  在Action文件中編寫需要測試的操作步驟,我這里就是發送udp請求,接受響應,判斷響應是否正確,代碼如下

Action()
{
    char*recvbuf;
    int recvlen=0;
    int rc=0;

    lr_start_transaction("Trans_UDP");
    lr_start_transaction("Conn_UDP");

    rc=lrs_create_socket("socket1","UDP","RemoteHost=127.0.0.1:8887",LrsLastArg);
    if (rc != 0) {
      lr_end_transaction("Conn_UDP",LR_FAIL);
      lr_end_transaction("Trans_UDP",LR_FAIL);
      return 0;
    }

    lr_output_message("Received:%d",rc);
    lr_end_transaction("Conn_UDP",LR_PASS);

    lrs_send("socket1","ReqBuf",LrsLastArg); //發送ReqBuf,ReqBuf為在data.ws中定義的發送變量  
    lrs_receive("socket1","RspBuf",LrsLastArg); //接收消息,存放在RspBuf中,RspBuf是在data.ws中定義的接收數組,注意數組長度一定要大於等於實際接收長度 

    lrs_get_last_received_buffer("socket1",&recvbuf,&recvlen);//把Socket最后接收的字節數組,長度放在recvlen中,內容放在recvbuf中  
   
    if(recvlen>=128) {
      lr_end_transaction("Trans_UDP",LR_PASS);
    } else {
      lr_log_message("Error UDP Received length:%d",recvlen);
      lr_end_transaction("Trans_UDP",LR_FAIL);
    }
    
//--------------斷開socket-------------- lrs_disable_socket(
"socket1",DISABLE_SEND_RECV); //--------------關閉socket-------------- lrs_close_socket("socket1"); return 0; }

  原理和上文提的基本一致,這里就不再多說了

編寫vuser_end

編寫結束時的操作,這里就是關閉init中的socket
vuser_end()
{
     //--------------斷開socket--------------
    lrs_disable_socket("socket0", DISABLE_SEND_RECV);

    //--------------關閉socket--------------
    lrs_close_socket("socket0");
    return 0;
}

運行測試腳本

  點擊start,執行腳本,運行無誤,說明腳本正確

    

 

至此測試腳本編寫完畢,可以正式開始性能測試了

性能測試

  •    始運行LR執行性能測試

  • 這里我們將剛剛編寫好的的測試腳本添加進去

  •  然后配置相關的測試參數,如並發數,測試時間等,開始測試

  • 觀察測試結果

最后在運行結束后,我們可以根據分析報告診斷性能測試結果,還可以配合jvisualvm工具診斷熱點方法,提升程序性能

總結

   我們可以LR可以配合jvisualvm工具診斷熱點方法,提升程序性能。如果有大神看出什么端倪的話,歡迎批評斧正,個人感覺還有提升空間


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM