LR總結筆記

性能:消耗的時間和資源的利用率
性能高:時間少、資源利用低
容量:相同空間,容量大,爲有利
接口測試越來越重要,各種模塊之間進行智能調用
httpwatch測試前端性能
virtualUser虛擬用戶
單交易基準測試:按規定測試
單交易負載測試:需求出發,所能承受的最大負載 100個 200個 1個小時
單交易壓力測試:需求出發,極限情況下系統會崩潰,是否具有自我恢復性100個 多少個小時會有問題
綜合交易測試:
綜合基準測試:
穩定測試:可靠性測試,平均無故障時間越長,修復時間越短越好。
性能測試:特定的負載條件下的性能指標數據。
不加think time接收的壓力大
計算性能時還要取消think time
PV可以刷,按照訪問次數
IP訪問,按照IP計算
吞吐量KB:單位時間接收請求後返回的數量,在對比、評估類測試Tomcat比Weblogic

性能需求:
功能點:一次交易有多個功能
業務:一次交易爲一次業務
交易:和服務的一次事件
提取性能需求:1.併發數 2.用戶頻繁使用,或存在大量用戶使用 3.對於被測對象很熟悉是否有必填
性能測試不做異常分析和測試
對於架構熟悉,對於網絡部署熟悉

性能分析:
1.分析被測對象業務規模
註冊1W,交易數800左右,峯值交易時間段20分鐘完成400左右,峯值併發30
2.分析測試點
a、註冊
根據業務規模分析,每天交易量在800左右,意味着至少有800個用戶登錄,系統存在賬號,測試1W,分解每天。另外,用2、8分析時間內最高訪問量,集中發生的時間。
b、登錄
某個時間點完成400次交易,單次登錄消耗的時間?要求不超過3s
c、訂票
d、查詢
3.確定對應指標

併發數:
查詢峯值得到併發數:使用SQL,使用count函數,datepass。
根據業務量計算併發數:10個註冊成功案例,2分鐘做完,需要幾個人,一個用戶消耗60s時間
HttpWatch打開後進行時間統計,利用loadrunner計算時間,
幾個人就是併發數。
啓動Server,如果報錯可以陪着config
hp\laodrunner\webtours\conf\httpd.conf的#ServerName localhost:1080的#去掉,再啓動服務
可以用HttpWatch計算登錄時間,或者使用loadrunning計算
啓動Virtual User Generator.exe
打開create a new script
打開web-http/html

打開首頁,輸入,提交,退出。

open_index
submit_login
sign_off

create a new script action
deleting the default action
click the recording button
setting the content of the URL address
strat recording
switch the action when the recording is completed
operating browser
close the recording when all operations are done 
Modify think time seconds
replay test
actioning think time and wasted time
click test results
select expand all
modify session:

單次登錄11s

日均200WPV
200*80%=160W
24小時*20%=4.8小時
單次登錄2s
一個用戶4.8*3600s/2=8640次

測試4.8小時能否完成160W以上請求。
===================================================
系統要求5分鐘(300s)內完成200次用戶註冊,響應時間不超過3s,成功率100%,cpu以及內存使用率不超過70%
單次註冊消耗時間10.86s

open_index
into_register
submit_register

300s/10.86=27次
200次/27次=8個Vuser
8*27次=216個測試數據
216*1.2倍=260個測試數據

準備測試數據

響應時間:服務器處理時間(經驗值2,5,8,10)2秒最好
==================================================
#define定義常量
#define COUNT 100
Action()

函數:
int sum(a,b){
  int x,y,z;
  x = a;
  y = b;
  z = x + y;
  return z;
}
Action(){
  lr_output_message("%d",sum(20,30));
  return 0;
}

條件:
Acton(){
  int random;
  random = rand()%3 + 1;//1,2,3隨機
  switch (random){
    case 1:
      lr_output_message();break;
    case 2:
      lr_output_message();break;
    default:
      lr_output_message();
  }
}

循環:
Acton(){
  int i = 1, sum = 0;
  int count;
  do {
    sum = sum + i;
    i++;
//  count = i;
  }while(i<=10);
//  lr_output_message("%d",count);
    lr_output_message("%d",sum);
    return 0;
}

可以用字符數組表示字符串char test[] = "afasdfd";
指針:變量的地址。
指針變量:專門存放變量地址的變量。int *p1,*p2;float *q;
&取地址符號(p1 = &i),*p1取指針變量的內容。

如果使用一個腳本創建100個賬戶,可以迭代100次。也可以使用10個虛擬用戶,每個用戶創建10個賬戶。但是要設置parameter 裏面unique並且設置Allocate Vuser values in the Controller爲 Allocate 10 values for each Vuser。

參數Unique Number:當選擇%03d,查看sample爲001,block是數據塊的意思,如果輸入10就是001-010個數字也就是一個虛擬用戶使用10個數字。另外使用拼接,可以"t{username}"。這樣就是少一些參數輸入。

=============================================
lr_output_message("第一次:%s",lr_eval_string("{paramtest}"));
lr_output_message("第二次:%s",lr_eval_string("{paramtest}"));
=============================================
增加檢查點:需要點擊Snapshot界面,選擇Honzontal下的Recording,同時選擇Page View下的要檢查的部分右鍵選擇Add Text Check Step,進入Find Text界面選擇Save count複選框並在後面填寫標誌位regsiterflag。
在代碼內添加Replace with Parameter,只需要右鍵選擇對應幾個字母,即可參數化之前設置好的參數。
命一個int regsitercount=0; 然後regsitercount = atoi(lr_eval_string("{regsiterflag}"));
if(regsitercount>0)lr_output_message("success");else "fail + %s",lr_eval_string("{username}");
檢查點中的Add Text Check Step,如果在Page View下右鍵找到有可能不是真正要檢查的字符。需要進入Http Data下的對應請求的Raw Data內HTML頁面代碼,找到對應的正確代碼纔可以。
==============================================
關聯函數:
查看前臺頁面代碼,可以看到name="userSession"。
定位提交表單的頁面右鍵,點擊屬性,可以查看對應的url,變然後查看Http Data,就可以查看到userSession的位置。
web_reg_save_param
==============================================
open_index submit_login into_flight find_flight select-flight pay_flight sign_off
賬戶需參數化,username和userSession。出發到達城市隨機。隨機某個具體航班。
如果成功,還要測試失敗是否也生效,代表是否正確的代碼。
web_reg_save_param("usersession","LB=userSession\" value=\"","RB=\"/>",LAST);
web_reg_find("Text=Welcome","SaveCount=loginflag",LAST);
if(atoi(lr_eval_string("{loginflag}"))>0)//lr_eval_string轉字符串,atoi轉int
lr("success");
return 0;
else
lr("fail");
return -1;

web_reg_save_param("flights","LB=\">","RB=</option>","ORD=ALL",LAST);
自帶隨機函數lr_paramarr_random("flights");

char *departcity,departcitys[30];
char *arrivacity,arrivacitys[30];
departcity = lr_paramarr_random("flights");
lr("%s",departcity);
sprintf(departcitys,"Value=%s",departcity);把Value=departcity變爲departcitys變量

可以直接更換Value=、、、爲departcitys。

設置{departdate}進入Parameter List中選擇Parameter type爲Date並可以更改%a/%d/%y爲%Y,就是年的全稱2018。

web_reg_save_param("fightline","RB={departdate}");
char *flightno;
char flightnumber[25];
flightno = lr_paramarr_random("flightline");
如果判斷參數的關聯:sprintf(fligghtnumber,"Value=%s%s",flightno,lr_eval_string("{departdate}"));

另外一種取隨機數:
int flightcount;
int departrandnum=0;
flightcount=atoi(lr_eval_string("{flights_count}"));
departrandnum = rand()%(flightcount/2)+1;
sprintf(departstr,"{flights_%d}",departrandnum);
lr(lr_eval_string(departstr));

SPDY
Google開發的基於TCP的應用層協議
Application        --- HTTP
Session            --- SPDY
Presentation(儀式) --- SSL
Transport          --- TCP

WebSocket
在 WebSocket API,瀏覽器和服務器只需要做一個握手的動作,然後,瀏覽器和服務器之間就形成了一條快速通道。
1. Header
互相溝通的Header是很小的-大概只有 2 Bytes
2. Server Push
服務器的推送,服務器不再被動的接收到瀏覽器的請求之後才返回數據,而是在有新數據時就主動推送給瀏覽器。

Clint-Headers
Request-Line:GET/HTTP1.1
Accept:text/html
Accept-Encoding:gzip
Accept-Language:zh-cn
Connection:keep-alve 保持長連接
Cookie:BAIDUID
Host:www.baidu.com
User-Agent:Mozilla

Headers-Received
Status-Line:HTTP1.1 200 OK
...

content:渲染後代碼...

linux:內存swap 有些程序長時間不操作,或物理內存不足啓動swap。
內存paging時時刻刻發生操作。
TCP 三次握手四次揮手
netstat -ae|grep "TIME_WAIT" |wc –l查看網絡中time_wait修改配置文件排除問題。

httpwatch:查看,支持自動化API查詢。Fiddler:本身代理Composer下的Parsed,可以拉拽一次協議查看並修改,端口8888,Inspectors下的Raw就是舊版的請求。並且可以測試https,需要Tools下的Fiddler Options下的https traffic。並且可以自定義服務器返回。firbug:修改前臺界面。colasoft:從網卡讀取數據。

netstat -ano,列出所有端口的情況。
tasklist | findstr "8888"

相應時間:客戶端65535、網絡、應用服務器、數據庫
1.DNS 2.Connect 3.Send 4.Wait
清楚DNS ipconfig /flushdns

網絡三個層次:核心層、匯聚層、接入層
網絡吞度量,網絡設備連接

應用服務器:
程序的健壯,小號資源合理
啓動壓縮(壓縮文本而非其他)
緩存
預熱
線程配置

數據庫:
索引是否正常使用(db2分區鍵)
SGA是否分配合理
多用關聯少用in
集合操作能用union all就不用union

最後客戶端接收數據進行渲染

性能指標有多個站在用戶和開發兩個方面:運行程序佔用,訪問量,持續服務,相應時間
開發:涉及合理,安全,效率,回收,擴展,readme等
top:cpu:load average 5 15分鐘負載(負載不能比CPU核數4倍還多)
負載階段:規劃、創建腳本、定義場景、執行場景和分析結果。
併發與並行、併發用戶數和在線用戶數、TPS和響應時間、點擊數、吞吐量、資源使用率、PV和UV
並行:真的同時執行,CPU多核同時進行任務。
併發:不一定同時執行。因爲有CPU有中斷,所以感覺單核可以做多個任務,實際沒有並行。
併發用戶數:有效的負載用戶。要一直操作。
在線用戶數:包括操作和不操作用戶。
transaction per second:每秒事物。每秒業務數。
相應時間:客戶端+網絡+服務器
點擊數:發出請求數。
吞吐量:單位時間被處理的業務或者請求量。
資源使用率:%
PV:一個URL,訪問量。
UV:一個用戶,訪問ip數量。
測試工具的協議纔會造成負載!
通信協議:標準協議、自有協議
工具要有更新纔有生命力,才學。
跨平臺的工具纔是好工具。
loadrunner jmeter Gatling IBM RPT was silk-performer
協議:Web SOAP FTP JDBC 等

問開發,經驗,看項目文檔,協議探測器(loadrunner自帶)
選擇協議,選擇的是與壓力模擬直接交互的中間件或者服務器,和後面的無關。再次強調,loadrunner錄製只與協議有關,和操作界面關係不大。

1.界面簡單解析 2.保存目錄解析 3.腳本結構解析
vuser_int()
lr_output_message("");
action()
vuser_end()
Replay Log再運行腳本log
Generation Log程序抓包的協議日誌

Tree可以樹狀圖顯示過程,選擇HTTP View,但是顯示慢。一般scrip即可。篩選的時候可以選擇tree模式,篩選包的時候可以選擇。

Replay Log中顯示運行時設置文件:Run-Time Setting file:

建立腳本後必須要保存,才能存入。.usr即可調取LR的腳本界面。
mdv.log,output.txt是Replay Log
default.cfg 是運行時設置文件
.bak是副本。.asc錄製的原始API調用。.grd包含數據庫腳本中網絡的列標題。default.usp保護腳本的運行邏輯,包括操作部分的運行方式。

F4配置number of iterations迭代次數action的次數,也就是業務的代碼,實際不停操作部分。

C語言的main函數由LR去控制。

錄製選項:Gerneral Recording中HTML-based script和URL-based script
HTML-based script:生成多個cookie,和一個函數,看不出過程。高級部分:Script type:A script describing user actions 模擬用戶先打開界面,才能發送表單,註釋開始會報錯。和 A script containing explicit URLs only 直接把表單提交到服務器,註釋開始打開頁面後面不會報錯。
URL-based script:生成多個cookie,和每一個包都的URL都列出來,所以看出所有的過程。高級部分:

註釋Ctrl + Alt + C

錄製選項:HTTP Properties Advanced中UTF-8可以中文輸出log。

事例jojo/bean

大部分使用的都是URL的方式:
基於瀏覽器的推薦使用HTML錄製,客戶端的推薦URL錄製。
但是如果瀏覽器內有js多次請求,有可能抓不到請求,就需要URL錄製。
當使用HTTPS,推薦使用URL的方式。

運行時設置文件:Run-Time Setting file:的解析。
可以選擇是否使用思考時間。
可以設置使用多大帶寬,一般使用最大帶寬。
browser的設置browser emulation:
HTTP的協議會有這個字段User-Agent:數值可以選擇或者直接寫入value。
爲了LR看到User-Agent需要打開擴展日誌:log---extended log---Data returned by server並且選擇---advanced trace 即可在日誌中看到
User-Agent根據後臺校驗的時候需要修改。
Simulate browser cache可以啓動,也可以不啓動,會在日誌中顯示。
Cache URLs requiring content把內容緩存和Check for newer versions of stored pages every visit to the page
這兩個都是更好的模擬瀏覽器。內存夠用就啓用URLs。Check可以模擬瀏覽器點擊刷新動作,RL會添加請求頭選項if-modified-since
,校驗更新時間,是否需要更新,會不停詢問,但是隻能是頁面內容,而圖片不可以。
如果按兩次F5瀏覽器會除去cache返回大量減少。
download non-html resources 下載非HTML資源,不勾就簡化只下載html。
Simulate a new user on each iteration 每次都運行三次握手四次揮手。

C編程:
LR是解釋型C語言。90%可以適用。
使用變量要提在最前一次性聲明!不能在後面定義。
錯誤:
int a = 10;
printf("%d",a);
int b = 10;
編譯錯誤!
全局變量global和局部變量(action end init)

char *p;
p = (char*)malloc(1024*sizeof(char));
free(p);

變量使用前,儘量初始化。
指針:
char var='A';
char *p=&var;
char *name = "LoadRunner";
l_o_m("var=%c",*p);//*p=p的內容,輸出:A
l_o_m("name=%s",name);//name=指針,輸出:LoadRunner
l_o_m("name=%s",*name);//輸出:L
return 0;
%d輸出整型 %c輸出一個字符 %s輸出所有字符串,因爲字符串""是有/0做爲最後一個標記,所以會輸出所有字符串。

數組:
char p[]={'A','B','C','D'};//字符數組是沒有/0,輸出:ABCDLoad Runner!
char s[]="Load Runner!";//輸出:Load Runner!
l_o_m("p=%s",p);
l_o_m("p=%s",s);
return 0;

c就是數組的首地址,但是字符數組是沒有/0,所以會繼續下面的內容,所以能不用字符數組儘量不用。

char s[]="Load Runner!"
sizeof(s)查看s的電腦識別長度多一個(包括/0一個長度),strlen(s)查看s的看到的長度。

a[1]="a"會造成會繼續下面的內容(包括/0一個長度),所以能不用規定數組長度儘量不指定長度,使用a[]="abc"。

if(m==0)
{}
else
{}
for(i=0;i<5;i++)
{}

通用函數:lr_output_message("");
與編程語言相關的函數:%d %s
與協議相關的函數:
本身三個函數可以互相調用
vuser_int()
action()
vuser_end()
並且LR可以選擇add files to script添加一個.h的文件,可以在右側的global.h下面顯示出來,還必須在action()的上面#include 'aaa.h',強行引入aaa.h的函數。
可以F1調用help,比如lr_think_time(),lr_get_host_name(),lr_whoami()獲得詳細信息,lr_get_attrib_string獲得屬性的字符串,可以返回一個指針,函數的使用方法:1通過運行時設置使用,2通過命令行
lr_get_attrib_string需要全局變量F4的additional attribute添加全局變量,如:hello:lr。
char *p = lr_get_attrib_string("hello");
可以輸出lr

真正壓力執行程序調用mmdrv.exe來執行腳本!
可以使用命令行執行:
"C:\Program Files\HP\LoadRunner\bin\mmdrv.exe" -usr C:\getparam\getparam.usr -out C:\getparam\result\ -hello loadrunner -loop 1
打印出loadrunner,和上面的hello:lr相似,就是可以直接用命令來調取lr_get_attrib_string的函數結果。直接修改腳本內容的變量!

LR可以設置錯誤的處理方式:General下的Miscellaneous,不勾易出錯誤中斷;和Preferences下的Advanced下的Non,不勾易出錯誤中斷。

在LR中運行時選擇QTP腳本,爲QTP腳本存放目錄下文件擴展名爲.usr的文件。
test.usp :包含腳本的運行邏輯包括actions部分的運行方式
在全局變量中:preferences---Non-critical resource errors as warnings可以把所有的報錯輸出,但是後面就不再執行了。
可以使用:miscellaneous---continue on error就可以繼續執行後面的程序。
lr_continue_on_error(0或者1)可以詳細設置處理錯誤的時候是否繼續,默認是退出,而且會覆蓋全局變量的錯誤方式設置。
lr_continue_on_error(1)
不再考慮出現錯誤
lr_continue_on_error(0)

lr_output_message---詳細輸出,哪裏都會寫入。
lr_log_message---只將message寫入到本地,不輸出到遠程controller。
lr_message---只將message寫入到本地,不輸出到遠程controller。
lr_error_message---紅色輸出,詳細輸出。

真正運行的時候要最小,只收error錯誤的日誌,減少干擾。所以建議選擇Log下的Standard log。
F10可以一步一步調試操作。可以設置斷點,還有右鍵代碼可以定位生成的日誌信息。還有右鍵可以打開目錄。

strcpy與strcat 從頭添加和從尾添加
strcmp函數 比較兩個字符串,相等返回零,1大於2返回正,1小於2返回負數。
atoi函數解析
sprinf
time

action(){
  char fullpath[1024],*filename = "logfile.txt";
  strcpy(fullpath, "c:\\tmp");
  lr_output_message ("fullpath after strcpy: %s", fullpath);
  strcat(fullpath, "\\");
  strcat(fullpath, filename);
  lr_output_message("Full path of file is %s", fullpath);

  return 0;
}
Action.c(12):fullpath after strcpy: c:\tmp
Action.c(18):Full path of file is c:\tmp\logfile.txt

action(){
  int i=0;
  char * s = "7 dollars";
  i = atoi(s);//轉換爲數字7
  lr_output_message("Price $%d", i);
  return 0;
}
Action.c(10):Price $7

Action(){
  int index = 56;
  char filename[64], * suffix = "txt";
  sprintf(filename, "log_%d.%s", index, suffix);//拼接
  lr_output_message("The new file name is %s", filename);
  return 0 ;

}
Action.c(10):The new file name is log_56.txt

Action(){
  typedef long time_t;
  time_t t;
  //Get system time and display as number and string 
  lr_message ("Time in seconds since 1/1/70: %ld\n", time(&t));
  lr_message ("Formatted time and date: %s", ctime(&t));
  return 0;
}
Time in seconds since 1/1/1970: 1416760912
Formatted time and date: Mon Nov 24 00:41:52 2014

與協議相關的函數
web_link與web_url(get)link只能有上下文關係,但是url可以直接。get的請求體沒有信息,只有請求頭,並且放入到url,限制了字數和保密缺陷,post卻有請求體。
web_submit_form與web_submit_data(POST) web_submit_form中的hidden自動發送,post的請求。
web_custom_request//萬能的,靈活並複雜,可以選擇URL-based script 高級內選擇Use web_custom_request only。
web_add_header web_add_auto_header //遇到自定義請求頭的時候,使用比較好。
web_get_int_property//可以拿到詳細的信息

Action(){
  web_add_header("gggg","loadrunner");
  web_url("WebTours",
    "URL=htt://127.0.0.1:1080/WebTours/",
    "TargetFrame",
    "Resource=0",
    "RecContentType=text/html",
    "Referer=",//從哪裏鏈接過來
    "Snapshot=t1.inf",//LR的快照信息
    "Mode=HTML",
    LAST);//結束
  lr_think_time(3);
}
GET /WebTours/ HTTP/1.1\r\n
gggg: loadrunner\r\n

Action()
{int HttpRetCode;
web_url("my_home",
  "URL=http://my_home",
  "TargetFrame=_TOP",
  LAST);
HttpRetCode = web_get_int_jproperty(HTTP_INFO_RETURN_CODE);
if(HttpRetCode == 200)
  lr_log_message("The script successfully accessed the My_home home page");
  else
  lr_log_message("The script fialed to accessd the My_home home page");
}

在腳本的任何系統的函數中,不能使用C語言的任何函數。但是在系統函數之間是可以使用任意C元素。否則會報錯,只能使用LR的制定參數等。

lr_load_dll函數的使用(可以引入外部.dll的函數),另外因爲LR是解釋C,所以如果用複雜的函數會很慢,所以最好壓縮或者轉dll的編譯文件,再引入:
vuser_init(){
  lr_load_dll("c:\\loadDll\\md5.dll");
  return 0;
}
函數原型:
char* Calculate(const unsigned char* pachSource,unsigned int nLen)
第一個是要加密的字符串,第二個是該字符串的長度。
action(){
  char *p = "LoadRunner";
  int len = strlen(p);//計算字符串長度
  char *result = (char *)Calculate(p,len);
  lr_output_message("結果是:%d",ressult);
  return 0; 
}

事務和參數化
添加事務lr_start_transaction("openindex");
結束事務並計算時間:lr_end_transaction("openindex");
但是要配對,如openindex。
Action(){
  int status;
  lr_start_transaction("openindex");
  status = web_url("WebTours",
    "URL=htt://127.0.0.1:1080/WebTours/",
    "TargetFrame",
    "Resource=0",
    "RecContentType=text/html",
    "Referer=",
    "Snapshot=t1.inf",
    "Mode=HTML",
    LAST);
  if(status == 0)
  lr_end_transaction("openindex", LR_PASS);
  else
  lr_end_transaction("openindex", LR_FAIL);
  return 0;
}

Action(){
  lr_start_transaction("openIndex");
  web_url("WebTours",
    "URL=http://127.0.0.1:1080/WebTours/",
    "Resource=0",
    "RecContentType=text/html",
    "Referer=",
    "Snapshot=t1.inf",
    "Mode=HTML",
    LAST);
  lr_set_transaction_status_by_name(LR_FAIL, "openIndex");
  lr_end_transaction("openIndex", LR_AUTO);
  return 0;
}
Action.c(19):Notify:Transaction "openIndex" ended with "Fail" status (Duration:2.3595 Wasted time:1.3553).
duration是總共的時間
Wasted time是LR使用的時間,但是沒有自編程腳本的時間沒有加入到Wasted time,而且Controller和Analysis的時間是兩個數減去的時間。

Action(){
  lr_start_transaction("openIndex");
  web_url("WebTours",
     "URL=http://127.0.0.1:1080/WebTours/",
    "Resource=0",
    "RecContentType=text/html",
    "Referer=",
    "Snapshot=t1.inf",
    "Mode=HTML",
    LAST);
  //lr_think_time(1);
  lr_output_massage("Duration = %lf -- Waste = %lf",
    lr_get_transaction_duration("openIndex"),//獲取duration
    lr_get_transaction_wasted_time("openIndex"));//獲取wasted_time
  lr_end_transaction("openIndex", LR_AUTO);
  return 0;
}
Action.c(17):Duration = 4.394222. -- Waste = 2.372381
Action.c(24):Notify:Transaction "openIndex" ended with "Fail" status (Duration:4.3595 Wasted time:2.3553).
think_time對於Duration有影響。

lr_wasted_time(wasteTime*1000);1000是毫秒
Action(){
  merc_timer_handle_t MasterT, timer;
  char save[1000];
  double wasteTime;
  int i;
  lr_start_transaction("openIndex");
  web_url("WebTours",
     "URL=http://127.0.0.1:1080/WebTours/",
    "Resource=0",
    "RecContentType=text/html",
    "Referer=",
    "Snapshot=t1.inf",
    "Mode=HTML",
    LAST);
  timer = lr_start_timer();
  for(i=0; i<(l * 1000); ++i)
    sprintf(save, "This is the way we waste time in a script = %d", i);
  wasteTime = lr_end_timer(timer); //return as msecond

  lr_wasted_time(wasteTime*1000);//把wasteTime也加入到wasted_time內

  lr_output_message("Duration = %lf -- Waste = %lf",
    lr_get_transaction_duration("openIndex"),
    lr_get_transaction_wasted_time("openIndex"));
  lr_end_transaction("openIndex", LR_AUTO);
  return 0;
}
Action.c(37):Duration = 10.627309 -- Waste = 9.282772//是LR加wasteTime的總共wasted_time時間。
Action.c(44):Notify:Transaction "openIndex" ended with "Pass" status (Duration: 10.6391 Wasted Time:9.2828)

lr_start_sub_transaction 提交子transaction,可以嵌套事務

具體事務中前臺,bean,數據庫各自浪費的時間不清楚,但是隻知道總的和是事務時間。

參數化:
Action(){

  web_submit_data("search",
    "Action=http://www.youdao.com/search",
    "Method=GET",
    "EncType=",
    "TargetFrame=",
    "RecContentType=text/html",
    "Referer=http://www.youdao.com/",
    "Snapshot=t2.inf",
    "Mode=HTML",
    ITEMDATA,
    "Name=q", "Value=test", ENDITEM,
    "Name=ue", "Value=utf8", ENDITEM,
    "Name=keyfrom", "Value=veb.index", ENDITEM,
    LAST);
  return 0;
}
那些可以參數化:可以查看F1找到parameterization,只能參數化LR的函數內的參數。
需要參數化:
1.登錄 2.一些和時間相關的,違反時間約束的 3.一些受其他字段約束的 4.一些來自其他數據源,例如數據庫 5.其他在運行過程中需要變動的。
在Tools內General Options中Display 點擊Show run-time viewer during rep 點擊Auto arrange windo可以打開顯示操作過程展示

選擇需要參數化的範圍右鍵,可以選擇Replace with a Parameter,可以選擇類型,或properties詳細設置。
設置好後在代碼會顯紅並且用{}括起來。

在General Options中Paraneterization中設置使用什麼符號括起來。

如果想看到參數化,必須在log中Extended log 中 Parameter substitution勾選。

進入properties詳細設置:可以設置數據的行和列,並且導入數據庫,選擇數據如何讀取,設置一行數據用逗號隔開。如果有數據1,創建數據二後選擇數據1可以關聯,如用戶名關聯密碼。

參數化會在保存目錄內生成.dat的文件。並且最後一個肯定有一個回車空行。

什麼時候改變參數化,其實就是如何切割數據池
select next row:獲取下一行數據的方式:順序,唯一(只能選擇一次)和隨機,特殊兩個數據關聯same line as username但是必須使用一個username的dat數據。
update value on:重新獲取下一個參數的時機(條件):每次迭代,每次遇到和永遠不變
when out of value:不夠用數據的時候:循環,報錯和用最後一個值

Unique,獨特,代表一次選擇後,後面不再選擇。
when out of value 當數據不夠用的時候
abort Vuser 失敗結束
Allocate Vuser values in the Controller,如何分配數據塊,可以自動按順序,或者每3個選擇一個塊。
Unique並且Once,那麼一個用戶就用一個數據。

File還可以更改random number會用的比較多,就是隨機從1-99

實例:保證用戶名和密碼配對

Action(){
  int a = 10;
  lr_output_message("變量的取值是:%d",a);
  lr_output_message("參數的取值是:%s",lr_eval_string("asd{output}"));
  return 0;
}
Action.c(5):變量的取值是:10
Action.c(7):參數的取值是:asd1

1.參數化和變量的區別:參數作用域遠遠大於局部變量,在一個action中的參數可以再另一個函數使用,而局部變量不行,除非是全局變量。
2.參數和變量的轉換:1參數轉換成變量 lr_eval_string(參數轉變量) 2變量轉換成參數 lr_save_string(把誰,轉成參數誰)

Action(){
  char name[]="LoadRunner";
  lr_save_string(name,"aaa");
  lr_output_message("參數的取值是:%s",lr_eval_string("{aaa}"));
  return 0;
}
Action.c(8):參數的取值是:LoadRunner

但是這個參數無法從Parameter List中不會有顯示。
數據庫的連接也是從數據庫中load到本地,所以可以連接JDBC等驅動獲得。Sepacify SQL statment manu 是可以自己選擇sql語句。

關聯服務器變化參數
LR只能判斷從協議上沒有問題,但是實際業務是無法判斷的。
1.所有驗證都肯定在輸出請求之前,就已經獲得了。
2.如session、X-CSRFToken等
3.可以類比,或確定知道後,在tree模式下,找到對應請求的值,右鍵選擇值,選擇Create Correlation,在腳本中會出現CorrelationParameter_1的參數,直接使用{CorrelationParameter_1}放到對應的函數的session值,就可以直接安裝響應取值。

查看函數web_reg_save_param_ex()中需要注意LB RB 左右側標記,只要左右邊界都唯一,就可以標記session。參數Scope可以選擇body all等或者head,就是區域值。
reg是註冊函數,必須放在關聯的參數上面,先生成這個函數才能關聯成功。

4.大部分都是hidden的type,並且放到請求頭。X-CSRFToken,跨站點保護參數。
web_reg_save_param("X-CSRFToken","LB=X-CSRFToken\" value=\"","RB=\"","Search=Body","Ord=1",LAST);
X-CSRFToken\" value=\"是左邊界
\"是右邊界,就是雙引號
Ord=1是如果搜索到多個,選擇第一個
日誌log的參數也需要打開

5.最好使用Fiddler的Composer來模擬排查,錄製後直接鼠標拖拽。
尋找失敗點後面的頁面請求,把成功的網頁請求放到Fiddler,並且刪除猜測的檢查數值。直到出現相同的返回錯誤代碼,基本可以找到。

同樣在LR中也可以使用web_add_header來篡改請求。

6.一般變化中無效驗證:Referer之前源跳轉網址等。

7.每一步,都要查看是不是值有不同多次請求!
同時對於每個檢查值都要記錄,因爲有時候同樣的檢查值會變化,不是一直都用一個檢查值。前後做值的對比,查看是否有變化。

集合點的概念,解析集合點函數:選擇insert的rendezvous,只能在action中添加集合點,事務中不要添加集合點,會停止事務。在controller併發的時候使用。

P27-P30
腳本開發的原則:簡單、正確、高效
單用戶循環一次,多次(Vugen)
多用戶循環一次,多次(controller)

第十講:
性能計劃編寫
1.1系統簡介
1.2性能測試目的
1.3性能測試策略
2.1系統組成分析
對於錯誤用例也要注意服務器的狀態

環境變化一定要和上級確定,需求一定要寫郵件做證據。
計算併發可以估算:在線用戶數*5%-20%
tps:每秒響應時間 2-8定律
準備工具:shell腳本或python腳本進行提取日誌信息。

檢查點:
儘量使用web_reg_find函數,不要中文,不能單單從協議層面判斷。
web_reg_find("Text=jojo", LAST);
Action.c(24):Registering web_reg_find was successful

web_find("Text Check","What=Welcome",LAST);可以全文搜索。但是需要勾選Run-time Settings的Rreferences的Enable Image and text check

第十一講
接口:協議HTTP POST GET
名詞解釋:
URL:
參數:
錯誤相應輸出:
錯誤碼定義:
例子:

vuser_init(){
  lr_load_dll("md5.dll");
  return 0;
}

  char secret_key[32] = "oweolsdoiowiwql";
  char api_key[32] = "zhangdanzhongxin";
  char method[32] = "datacenter.getBillGas";//開發的一個接口
  char timeOfSecond[12];
action(){
  char bd_sig[100];
  typedef long time_t;
  time_t t;
  springf(timeOfSecond,"%ld", time(&t));//拿到時間
  lr_save_string(timeOfSecond, "call_id");//字符串轉參數
  lr_output_message("%s", timeOfSecond);//打印時間
  //bd_sig生成方式:MD5(api_key+call_id+method+secret_key))
  strcpy(bd_sig,api_key);
  strcpy(bd_sig,timeOfSecond);
  strcpy(bd_sig,method);
  strcpy(bd_sig,secret_key);
  lr_save_string((char*)Calculate(bd_sig,strlen(bd_sig)), "MD5");
  //lr_output_message("%s", md5);
  web_reg_save_param("return_code","LB=error_code\":\"","RB=\"","Search=Body","Ord=1",LAST);
  lr_start_transaction("selectGas");
  web_custom_request("t1",
    "URL=http://192.168.21.67:8080/openapi/datacenter?api_key=zhangdanzhongxin&method=datacenter.getBillGas&call_id={call_id}&bd_sig={MD5}&format=json&req_charset=utf-8"
    "&mobile=13800138000&period=201404"
    "&result_fields=All",
    "Method=GET",
    "Snapshot=t1.inf",
    "Mode=HTML",
    LAST);
  lr_end_reansaction("selectGas", LR_AUTO);
  //業務確定是否成功
  if(strcmp(lr_eval_string("{return_code}"),"0") && strcmp(lr_eval_string("{return_code}"),"300"))//比較函數,C語言中比較只能用函數
{
    lr_error_message("no 0 or 300, is %s, EXIT",lr_eval_string("{return_code}"));
    return -1;
  }
  lr_output_message("********************");
}

亂碼出現:web_reg_save_param("error_code","LB=error_msg\":\"","RB=\"","Search=Body","Ord=1",LAST);
使用另外函數單獨處理亂碼:lr_convert_string_encoding(lr_eval_string("{error_code}"),
LR_ENC_UTF8,LR_ENC_UNICODE,"stringInUnicode");
lr_output_message("%s",lr_eval_string("{stringInUnicode}"));

如果由format=json變成format=xml,就需要調取web_reg_save_param_xpath();
tree模式對於xml模式支持比較好可以方便查看。
web_reg_save_param_xpath("ParamName=return_code","QueryString=//response/error_code",SEARCH_FILTERS,"Scope=Body",LAST);

啓用controller,點擊tools選擇Create Controller Secenario。
可以選擇Goal 或者 Manual,Manual可以選擇多少個用戶併發,選擇負載生成器,建議虛擬機出一臺專用負載機。

Design設計模式
兩種模式:Show Convert Scenario Mode Warning轉換爲數量和Convert Scenario to the Percentage Mode轉換爲百分比
在Scenario Groups下的add Group添加腳本路徑。
在Scenario Schedule下的Schedule by:Scenario 和 Group更多的設置選項。Scenario 把所有的腳本都作爲一組統一調配,Group 可以更精細的設置在哪個組結束後開始這選定的一組,壓力要慢慢加初始化,最後退出也建議緩慢退出。
在Scenario Schedule下的Run Mode:Real-world schedule更多的設置選項 和 Basic schedule。對於起伏的併發數測試,建議使用Real-world。但是一般測試選擇Basic,除非是長時間穩定測試選擇Real-world。
在Scenario Groups下的Run-Time Settings裏面很像script裏面的設置,但是各自負責各,不是通用。建議在運行錯誤在提示日誌,think time默認是打開的,會執行script裏面的think time時間。並且根據不同腳本地址也可以設置不同的設置。
保存的Design是.lrs文件,可以直接雙擊打開controller。

Run啓動
把Available Graphs可以直接拖拽藍色有數據的圖標到界面。
可以直接點擊Vusers...進行查看和操作。可以隨時調節壓力。
點擊stop的時候Vuser的設置可以選擇tools裏面options裏面Run-Time Settings,when stopping Vusers可以設置。

負載生成器
添加負載生成器選擇Scenario下面Load Generators...。Name就是IP,添加後選擇disconnect測試一下。
安裝負載生成器後必須要啓動,LoadRunner Agent Service。magentservice.exe就是負載生成器。
啓動負載生成器後也要監視生成器的軟硬件配置資源。

mmdrv
當Run-time Settings 裏面的Miscellaneous 的Multithreading是以run vuer as a thread跑的時候,以50爲一個mmdrv開始跑。但是以進程方式跑的時候就是幾個vuser就幾個mmdrv。以進程安全但是耗用資源,以thread不安全,可能共享內存,但是更節約。

IP欺騙 IP spoofer
更加模擬真實客戶的不同IP,char *ip;ip = lr_get_vuser_ip();if(ip)lr_output_message("%s",ip);
還要選擇Scenario下的Enable IP Spoofer設置。並且要在對應負責生成器上添加多個ip。必須要靜態ip,選擇高級,添加ip。LR也有工具可以添加負載生成器的ip,IP Wizard。

集合點
lr_rendezvous("myRende");可以查看scenario內的Rendezvous。可以控制vuser在某一時刻同時操作某一動作。當滿足條件時同時釋放。在Rendezvous內查看Policy,當所有正在跑用戶到時釋放,當所有用戶包括失敗的用戶到時釋放,當多少個用戶到了再釋放,等待到某一時刻釋放集合點。

自定義數據採集
Note很重要
int i;
for(i=0;i<100;i++)
lr_user_data_point("cpu",i);

Analyze建議模板
數據保存access,文件是.mdb。啓動Analyze可以直接點擊controller的圖標。打開後馬上保存,下次打開會快很多。
Total Throughput(bytes):總吞吐量
Total Hite:總的http請求數
Transaction Summary下的Std.Deviation標準方差,反映是否足夠平均分佈,越接近平均值,STD越小。
左側Properties內的Filter可以過濾。Percentile可以更改90%的數據統計。
Hits per Second 服務器每秒相應的http請求。左側有Properties可以更改圖表。
Throughput 網絡的吞吐量:1Gb = 1000Mb 1Mb = 1000Kb,網絡傳輸單位。硬盤也是1000GB,不是1000G,存儲是Byte。1000Mb/8bit/Bye,8bit = 1Bye。1000M/8 = 125MB/s 也是理論每秒傳輸的存儲量,實際1000M達到60%以上爲負載。
Average Trans...esponse Time 平均事務的相應時間。會有問題,建議關閉再打開,左側Graphs右鍵選擇增加Graph。

Web Page Diagnostics
在reports裏增加Graph,Page Downlo...Breakdown是清楚看到各個層的相應時間。
DNS Resolution DNS解析時間
Cronection Time 連接時間,TCP進行三次握手四次揮手
SSL Handshaking Time HTTPs纔有SSL
FTP Authentication FTP服務器的時間
First Buffer Time 從發送請求到接受第一個請求的之間時間
Receive Time 接受時間,從第一個接收到最後一個接受時間
Client Time 客戶端處理時間
Error Time
詳細解釋可以參考Analysis User Guide

圖標的合併
拐點上是不可接受,也就是角度很大,過陡;拐點下是可以接受,也就是角度很小。
合併需要x軸單位一致。點擊圖表右鍵的Merge Graphs
Overlay 共享一個x軸
Tile 共享一個x軸,其中一個在上面。
Correlate 取消兩個圖表的x軸,並把兩個y軸作爲數軸x和y軸。方便查看拐點的圖表。

可以生成報告,可以參考。

在Controller下生成的Transaction時間,可以初步判斷是否有問題。
先在單腳本時估計一下,是否時間一樣。如果一樣,那就是單腳本的問題,不是controller併發的問題。

查看腳本是否規範請求。是否和真實場景一樣。

如果有報錯,要雙擊打開。

如果接口優秀,也會報錯,可以增加think time,來讓客戶端負載生成器回收端口。並且在controller內也要設置think time的有效百分比。

查看數據庫:mysql -q 
user datacenter
show tables
show create table Bill_Electric顯示錶的建表結構。
查看錶缺少UNIQUE KEY '' () USING BTREE,聯合組件。
alter table Bill_Electric add unique index AK_UK_Bill_Electric('AccountNo','Mobile','Period')USING BTREE; 表內加入組件。
show variables like '%query%';
set global slow_query_log=1;
set global log_queries_not_using_indexes = 1;

增加一些知識:數據庫:安裝重啓,基本SQL語句,數據庫架構,數據庫原理,mysql的組建、引擎、man查詢幫助、回表、聯合索引,

空P43 第十三講

新建腳本時,可以選擇java內的java vuser。是編譯的,所以要裝JDK,錯誤提示更精確。Run-time Setting內的Java VM下的Use specified JDK,指定JDK爲C:\jdk-1.6
全部寫在action內,不要去其他地方寫代碼。
不足:有些語法支持不好,例如靜態代碼塊,少用不常用的語法和功能。有時因爲緩存,而需要切換JDK,才能正常。
不足如下:
class StaticBlock1{
  static{
    System.out.println("H");
  }

  public static void main(String[] args){
     System.out.println("L");
  }
}
out:H
out:L
靜態代碼塊,會在new後馬上開始執行,不需要調用。

只有一個類是public,定義class可以在任何位置。

如果需要引入外部的class文件,只需要把文件放入到保存的文件夾內,就可以直接new了。或者在Run-time Setting內classpath添加jar包。

注意:1.腳本中包括自定義的類,需要確保類是線程安全的,如果不確定,使用進程方式,可以充分隔離。
線程安全,同一個對象或變量,被線程爭搶。沒有修改肯定是安全的。線程安全是很難檢測的,但是在大壓力或者CPU資源緊張的時候相對容易發現。
import lrapi.*;
public class Actions{
  private static int iteration_counter = 0;
  public int init(){
    return 0;
  }
  public int action(){
    iteration_counter++;
   return 0;
  }
  public int end(){
    lr.message(iteration_counter);
    return 0;
  }
}
只能加鎖
不要再LR內自己加線程,要LR來加線程。

開發Java Vuser:
1.是否使用(1.強大的開源類庫。2.更方便使用開發的自定義的類。)
2.在eclipse中編寫一個正確的模擬代碼
3.將eclipse代碼移到LR中
4.結合業務特點,對腳本進一步增強
5.使用Controller運行多用的JavaVuser

P46
一般遇到Socket使用java
public class Actions{
  private SendOverSocket sos = null;
  private String receiver = null;
  private int version;
  public int init() throw Throwable{
    sos = new SendOver
  }
}

從web腳本轉化Java Vuser
1.使用sed.exe
2.將要轉換的web腳本複製出來並保存到文本中
3.參數界定符部分需要由於{}手動改成<>
4.打開DOS
5.切換到C:\Program Files\HP\LoadRunner\dat
6.運行..\bin\sed -f web_to_java.sed c:\web.txt > c:\java.txt
7.創建參數並進行其他操作


第15講--虛擬與現實的結合-探索Java虛擬機
Java虛擬機:
虛擬化技術:所謂虛擬化技術就是將事物從一種形式轉變成另一種形式,最常用的虛擬化技術有操作系統中內存的虛擬化,實際運行時用戶需要的內存空間可能遠遠大於物理機器的內存大小,利用內存的虛擬化技術,用戶可以將一部分硬盤虛擬化爲內存,而這對用戶是透明的。
JVM的啓動流程:
java xxx
裝載配置尋找jvm.cfg
根據配置尋找JVM.dll:JVM.dll爲JVM主要實現
初始化JVM獲得JNIEnv接口:JNIEnv接口是爲JVM接口,findClass等操作通過它實現。
找到main方法並運行。

查看虛擬機進程:
package com.test;
public class Test {
public static void main(String[] args) throws InterruptedException {
    System.out.println("************start*************");
    Thread.sleep(30000000);
    System.out.println("*************end**************");
}
}
查看任務管理器內啓動javaw.exe *32

Java虛擬機運行時數據區結構圖

http://www.catalannuan.com/2015/04/02/about-jvm/

系統資源監控
windows:
使用loadrunner直接監控,但是C盤必須能訪問
使用性能工具

linux


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章