qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問 http://qaseven.github.io/

          使用LoadRunner進(jìn)行服務(wù)器性能測(cè)試

           由于項(xiàng)目進(jìn)入尾聲,需要進(jìn)行性能測(cè)試,沒有專業(yè)的性能測(cè)試工程師,只好自己動(dòng)手,研究一下loadrunner.
            發(fā)現(xiàn)loadrunner對(duì)web測(cè)試介紹比較多,牽涉到winsocket測(cè)試的資料極少,不過到處找一找,研究一下,也是可行的.
            先說一下我們的協(xié)議,采用tcp協(xié)議,與客戶端采用自定義二進(jìn)制流的方式進(jìn)行通信.遵從普通的自定義協(xié)議的方式,即協(xié)議結(jié)構(gòu)采用包頭+包體的形式,包頭為固定大小的長(zhǎng)度,并在包頭中加入包體總長(zhǎng)度的字段.
            好了,下面可以用loadrunner進(jìn)行協(xié)議測(cè)試了.首先想法在PC上實(shí)現(xiàn)一個(gè)簡(jiǎn)單的協(xié)議生成軟件,我采用python進(jìn)行編制,將協(xié)議跑一遍,然后用loadrunner進(jìn)行錄制.由于是針對(duì)單個(gè)的協(xié)議錄制,因而在loadrunner中生成的腳本一目了然.考慮到同一條協(xié)議根據(jù)不同的條件,返回的數(shù)據(jù)是不一樣的,因此腳本稍有點(diǎn)復(fù)雜.
            錄制的腳本默認(rèn)采用函數(shù)lrs_receive()來接收腳本,根據(jù)loadrunner的匹配規(guī)則,默認(rèn)用data.ws中recv buf 中指定的長(zhǎng)度來進(jìn)行匹配,這樣,由于同一個(gè)協(xié)議返回的數(shù)據(jù)總是不斷變化的,就必然導(dǎo)致測(cè)試不通過的情況.在網(wǎng)上查到,可以通過某個(gè)設(shè)置使得每次達(dá)到錄制時(shí)的數(shù)據(jù)量即可,但這樣做有個(gè)明顯的缺陷,每次讀到到指定的數(shù)據(jù)后就不讀取了,針對(duì)短連接,或是只測(cè)試一次的還可以,要是長(zhǎng)連接,需要不停發(fā)送和接收的,必然出現(xiàn)測(cè)試不準(zhǔn)確的問題.
            以下為解決方法,將lrs_receive改為lrs_receive_ex,并將一次讀取改為兩次讀取,第一次讀取固定大小的包頭,讀完包頭后,解析出包體的大小,然后再讀取包體.
            此方法適用所有自定義winsocket協(xié)議,附上相關(guān)腳本.
          /********************************************************************* * Created by Mercury Interactive Windows Sockets Recorder * * Created on: Fri Jul 13 16:08:19 *********************************************************************/
          #include "lrs.h"
          vuser_init()
          {
          lrs_startup(257);
          lr_start_transaction("create_socket");
          lrs_create_socket("socket0", "TCP", "RemoteHost=127.0.0.1:110",  LrsLastArg);
          lr_end_transaction("create_socket", LR_AUTO);
          return0;
          }
          /********************************************************************* * Created by Mercury Interactive Windows Sockets Recorder * * Created on: Fri Jul 13 16:08:19 *********************************************************************/
          #include "lrs.h"long getNextRecvLen(char* socketID)
          {
          int NumberOfBytes = 0;
          int NextRecvLen = 0;
          char *Buffer;
          lrs_get_last_received_buffer(socketID, &Buffer, &NumberOfBytes);
          memcpy((char*)&NextRecvLen, Buffer+20, 4);
          lr_log_message("last_received:%d, NextRecvLen:%d", NumberOfBytes, NextRecvLen);
          return NextRecvLen;
          }
          int receive_ex(char* socketID, char* buf)
          {
          long NextRecvLen = getNextRecvLen(socketID);//getNextRecvLen("socket0");char flag[50];
          memset(flag, 0, sizeof(flag));
          sprintf(flag, "NumberOfBytesToRecv=%d", NextRecvLen);
          lr_log_message(flag);
          lrs_receive_ex(socketID, buf, flag, LrsLastArg);
          }
          void doOneThing(int index)
          {
          char sendbuf[50];
          char recvbuf1[50];
          char recvbuf2[50];
          char transbuf[50];
          memset(transbuf, 0, sizeof(transbuf));
          sprintf(transbuf, "one_send_recv_%d", index);
          lr_start_transaction(transbuf);
          memset(sendbuf, 0, sizeof(sendbuf));
          memset(recvbuf1, 0, sizeof(recvbuf1));
          memset(recvbuf2, 0, sizeof(recvbuf2));
          sprintf(sendbuf, "buf%d", 2*index);
          sprintf(recvbuf1, "buf%d", 2*index+1);
          sprintf(recvbuf2, "dbuf%d", index);
          lrs_send("socket0", sendbuf, LrsLastArg);
          lrs_receive_ex("socket0", recvbuf1, "NumberOfBytesToRecv=32", LrsLastArg);
          receive_ex("socket0", recvbuf2);
          lr_end_transaction(transbuf, LR_AUTO);
          }
          Action()
          {
          lr_rendezvous("read_all_req_0");
          doOneThing(0);
          }
          /********************************************************************* * Created by Mercury Interactive Windows Sockets Recorder * * Created on: Fri Jul 13 16:08:19 *********************************************************************/
          #include "lrs.h"
          vuser_end()
          {
          lrs_close_socket("socket0");
          lrs_cleanup();
          return0;
          }
            由于是分兩次讀取數(shù)據(jù),必然讀取的內(nèi)容與錄制的會(huì)稍有不同,幸好我們判斷成功與否不是用返回的數(shù)據(jù)進(jìn)行比較,而只是核對(duì)一下數(shù)據(jù)的大小,因此完全可以手動(dòng)修改數(shù)據(jù)腳本,以下為在錄制的基礎(chǔ)上手工修改的腳本(注意,只是更改了接收端)
          send  buf0 28
          "Test"
          "\x00\x1b\x00\x00\x00"
          "\x00\x00\x00\x00"
          "\x12\x01\x00\x00\x00\x01\x00\x00\x00"
          "\x02\x00\x01\x00\x01\x00"
          recv  buf1 -1
          recv rbuf0 -1
           

          posted on 2014-08-27 10:32 順其自然EVO 閱讀(870) 評(píng)論(0)  編輯  收藏 所屬分類: loadrunner

          <2014年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 康马县| 衡阳市| 伽师县| 龙胜| 南川市| 常熟市| 舒城县| 遂宁市| 修文县| 安乡县| 安徽省| 揭阳市| 永春县| 抚顺县| 神池县| 灵台县| 小金县| 吉林省| 黔西| 六安市| 桓台县| 佛学| 马山县| 日喀则市| 秭归县| 镇安县| 南通市| 神农架林区| 定日县| 板桥市| 义乌市| 芜湖市| 宜昌市| 南漳县| 元谋县| 汉中市| 晋宁县| 禄丰县| 湘潭市| 舞阳县| 通榆县|