负载测试、压力测试、配置测试、并发测试、可靠性测试、基准测试
P3 P4
系统资源监控
windows:
1.使用loadrunner直接监控,但是C盘必须能访问,在LR的Monitors下面有Add Measurements可以添加度量
2.使用性能工具:在计算机管理内---性能---监视工具---性能监视器,可以查看当时性能。
Windows性能日志
Windows Server 2008引入了数据收集器集和报告。利用数据收集器集可以指定希望跟踪的性能对象和计数器集。
可以使用单一数据集生成多个性能计数器和跟踪日志,还可以:
(1)指定访问控制,以管理谁可以访问所收集的数据。
(2)为监视创建多个执行计划和停止条件。
(3)使用数据管理器控制所收集数据和报告的大小。
(4)根据所收集的数据生成报告。
性能---数据收集器集---用户定义---右键新建数据收集器集---选择手动创建---选择创建数据日志勾选性能计数器---添加计数器---设置时间间隔单位为秒或其他---保存位置:%systemdrive%\PerfLogs\Admin\Sql性能监视器---选择保存并关闭---找到刚创建的集,内有一个数据收集器,右键属性---从“日志格式”列表中选择“逗号分隔”---找到刚刚创建的集,右键属性---在计划选项卡上,添加监视计划,然后结束设置。
内存三个指标:Available Bytes(可用,不小), Memory pages(硬页错误从磁盘读取或写入速度,不高),Page Faults(出错页面的平均数,不高)
内存泄露:1.进程分配内存后,但未将用完的内存回收,该进程越来越大。2.观测内存分配池Pool Paged Bytes,内存分配池中可用内存消耗不断上升。
磁盘四个指标:%Disk Time(忙于读写请求服务的时间百分比,<10),Averge Disk Queue Length(平均队列,<0.5),Averge Disk Seconds/Read/Write(平均读写,无,但分寻道、旋转延迟、数据传输)
CPU三个指标:%ProcessorTime(使用率<85,user进程 system进程),%UserTime(user进程),%PrivilegedTime(system进程)
一般采集:%Disk Time(PhysicalDisk_Toal) %Processor Time(Processor_Toal) Avaiable MBytes(Memory) Bytes Received/sec(Network Interface Intel(R)82567LM Network Connection) Bytes Sent/sec(Network Interface Intel(R)82567LM Network Connection) Processor Queue Length(System) Avg Disk Queue Length(LogicalDisk D:)
linux
1.命令监控
CPU三个指标:运行态、就绪态、等待态(阻塞态)1.CPU队列 2.CPU繁忙程度 3. CPU高密集程序
CPU队列、CPU繁忙程度命令:vmstat 2 10 隔2秒 采集10次
r 可运行的内核线程平均数据,不能大于CPU的数目
b VMM虚拟内存等待队列中的内核线程平均数 <核数*0.7 2盒小于1.4
cs 每秒上下文切换次数
us和sy和id 是cpu的用户和系统进程和空闲比( <15)
CPU高密集程序命令:ps -au 进程 au由高到低排列 ef由低到高排序
内存SWAP(使用虚拟内存的块)Buffers(temp文件读取)
命令:vmstat 2 10 隔2秒 采集10次
buffer越少越好,cache越多越好。si input,so output比例应该为0,如果非0就是要靠SWAP调虚拟内存
查看统计信息命令:vmstat -s
查看更细致信息命令:ps -v
RSS进程大小
磁盘三个指标:物理转对应多个逻辑转,逻辑转对应多个文件系统,文件系统对应挂载点,
命令:iostat 5 2 隔5秒 采集2次
sda是逻辑转
命令:如果没有安装sysstat包 rpm -ivh systat-7.0.2-3.el5.i386 包括iostat、mpstat、sar和sa工具
sar -d 3 3
Avwait就是队列长度
测试磁盘当时空负载和负载的读写当时情况,命令:
写入:time dd if=/dev/zero of=/test.dbf bs=8k count=30000
读取:tiem dd if=/dev/sda1 of=/dev/null bs=8k count=30000
读写:tiem dd if=/dev/sda1 of=/test1.dbf bs=8k count=30000
网络使用工具监控
2.nmon监控可以记录并且写报告
安装nmon后 更改权限为chmod 777 文件夹
Web 服务监控
Apache 需要打开LoadHodule status_module modules/mod_status.so才能打开监控模式
在地址栏输入http://localhost/server-status
Total accesses:总请求数
Srv PID Acc M SS Req Conn Child Slot Client VHost Request
PID 进程
Req 请求数
Conn 连接数
Child 孩子间接
Request 请求方式
M的方式可以查看下面注释
带参数输入url:?auto是否动态刷新,refresh刷新秒
如:http://localhost/server-status?auto&refresh=5
Total Accesses:总连接量
Total kBytes:接受总字
Uptime:运行总时间
ReqPerSec:平均每秒请求数
BytesPerSec:平均每秒发送的字节数
BytesPerReq:平均每个请求发送的字节
BusyWorkers:正在工作数(线程)
IdleWorkers:空闲数(线程)
运行时配置:
1.AllowOverride是否允许覆盖,一般是None
2.HostnameLookups 主机对DNS的查找,一般是off
3.FollowSymLinks 是否重复检查连接符的安全性,可以设置
Options FollowSymLinks
Options-FollowSymLinks+SymLinksIfOwnerMatch
4.内容协商Content Negotiation
多路模块处理
windows:mpm_winnt
linux:preforkMPM\workerMPM
ThreadsPerChild 每个孩子的进程数 最大是1920,建议100-500之间
MaxRequestsPerChild 默认为0,建议是1以上数值。
MaxSpareServers 自动为MaxSpareServers+1,建议比MinSpareServers,如果系统繁忙会启动这个参数,多余的会被杀掉。
ServerLimit要比MaxClient大
测试的时候去掉ExtendedStatus On和LoadHodule status_module modules/mod_status.so两个模块加#
但是tomcat没有涉及到!
数据库监控:
数据库内外压力内存瓶颈:
CPU瓶颈:
磁盘瓶颈:
等待类型:1.丢失更新 两个数据同时对一条数据更新,结果更新的数据并不是两个数据的总和
2.脏读 一个数据,其中一个人数据还原到原始数据,被另外一个人已经使用新数据。
3.不可重复读 因为数据一直在更新,所以被读取永远不是最新的。
4.幻影 一个插入或删除数据,在另外一个关联的表内没有做相同的插入或删除数据,造成其中一个多出数据。
数据库的监控使用软件
可以捕捉阻塞实践,
性能:消耗的时间和资源的利用率
性能高:时间少、资源利用低
容量:相同空间,容量大,为有利
接口测试越来越重要,各种模块之间进行智能调用
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。
web_reg_find("Text=Welcome","SaveCount=loginflag",LAST);
在代码内添加Replace with Parameter,只需要右键选择对应几个字母,即可参数化之前设置好的参数。
命一个int regsitercount=0; 然后regsitercount = atoi(lr_eval_string("{regsiterflag}"));
if(regsitercount>0)
lr_output_message("success");
return 0;
else "fail + %s",lr_eval_string("{username}");
return -1;
检查点中的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=","ORD=ALL",LAST);
自带随机函数lr_paramarr_random("flights");
尽量不能用参数化,尽量用web_reg_save_param("flights","LB=\">","RB=","ORD=ALL",LAST)
抓出20个值,然后需要容器来随机。
departcity就是容器,lr_paramarr_random("flights");
char *departcity;
departcity = lr_paramarr_random("flights");
lr_output("%s",departcity);
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。
在find_flight内设置:
web_reg_save_param("flightling","LB=outboundFlight\" value=\"","RB={departdate}","ORD=ALL",LAST);
在select_flight内设置:
char *flightno;
char flightnumber[25];//要把这个变量提到find_flight()变量外面,改变作用域,使局部变量变成向下都可以用的变量,下面的pay_flight()才能用。
flightno = lr_paramarr_random("flightline");
sprintf(fligghtnumber,"Value=%s%s",flightno,lr_eval_string("{departdate}"));
lr("%s",fligghtnumber);
如果判断参数的关联: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));
=======================================================
性能测试:
1、注册 2、登录 3、订票
注册:open_index into_register submit_register
登录:open_index submit_login sign_off
订票:open_index submit_login into_flight find_flight select_flight pay_flight sign_off
1.交易量测试,时间段内完成的业务量是否符合要求(优先级高!)。
2.并发测试,顺时值的并发,不存在持续时间,是否并发完成系统正常。
单交易基准测试
注册、登录、订票分别进行测试
不同业务为1小时不同用户,不同并发,响应时间少,业务成功100,CUP内存80。
单交易负载测试
注册、登录、订票分别进行测试
不同业务一起不同并发,查看性能表现。
单交易压力测试
注册、登录、订票分别进行测试
不同业务在高并发下,持续多个阶段小时,性能的表现。
综合基准测试
注册、登录、订票一起综合
加并发加时间。
综合稳定性测试
注册、登录、订票一起综合
最终复杂验证:
1.交易量测试,时间段内完成的业务量是否符合要求(优先级高!)。
2.并发测试,顺时值的并发,不存在持续时间,是否并发完成系统正常。
不同业务在高并发下,加并发,持续多个阶段,加时间,查看性能的表现。
如果确定并发数,那么在一定时间内,肯定实际业务量会变化;同样确定实际业务量,那么在一定时间内,并发数肯定也会变化。
单交易基准测试
注册支持1小时5000用户注册,并发不少于30,响应时间不超过3秒,业务成功100,服务器CUP及内存不超过80。
登录支持1小时10000用户登录,并发不少于100,响应时间不超过3秒,业务成功100,服务器CUP及内存不超过80。
订票支持1小时2000用户注册,并发不少于20,响应时间不超过3秒,业务成功100,服务器CUP及内存不超过80。
不同业务为1小时不同用户,不同并发,响应时间少,业务成功100,CUP内存80。
单交易负载测试
注册功能验证30、50、80个并发时,性能表现。
登录功能验证100、120、150个并发时,性能表现。
订票功能验证20、50、80个并发时,性能表现。
不同业务一起不同并发,查看性能表现。
单交易压力测试
注册功能验证在30个并发1小时、4个小时、8小时,性能表现。(如果注册需要10秒,1小时可以做360次,5000/360=13个并发,就要用14个并发测试)
***如果确定并发数,那么在一定时间内,肯定实际业务量会变化;同样确定实际业务量,那么在一定时间内,并发数肯定也会变化。***
登录功能验证在100个并发情况下1小时、4小时、8小时,性能表现。
订票功能验证在20个并发情况下1小时、4小时、8小时,性能表现。
不同业务在高并发下,持续多个阶段小时,性能的表现。
综合基准测试
更具实际业务情况分解,各个业务占比,涉及总和场景的指标
通过历史记录,发现某一小时内,业务量达到某个峰值,且注册交易占比23%,登录占比38%,订票占比39%。
扩容后是现有业务两倍,占比不变,业务量加大。
在基准测试的基础上,持续运行较长时间周期,验证稳定性(100个持续并发运行8个小时,验证服务器的能力)
加并发加时间。
用户登录来模拟:
单交易基准测试:
1.并发测试,如果有三个业务
2.交易量测试,如果有三个业务
单交易负载测试:
单交易压力测试:
2种*3类*3功能=18个场景
最终验证:1.交易量测试,在一定时间内,单用户跑多少次,看是否符合要求。
2.并发测试,不同业务在高并发下,加并发,持续多个阶段,加时间到在一定时间内,查看性能的表现。
===========================================================
进入analysis
首先也是保存结果,并且结果可以作为性能测试报告的一部分。
analysis是有事务的,事务是最小单元。标准方差越小越稳定。
在Summary report内可以调整百分比,来查看多少合乎标准。summary内没有系统、网络资源的情况。
running vusers表:查看负载压力是否产生正确
hits per second表:每秒请求数,也是客户端发给服务器的压力数。
throughput表:吞吐量,和请求数表相似,可以把上面的请求数表合并右键选择merge graphs,是网络的数字。
查看表的筛选器,是否包含think_time:右键选择set filter,查看think_time。在场景内自动会有think time,但是脚本和分析时一般不会有think time。set filter相当于SQL语句中的where,group by相当于SQL语句中的group by,可以更细致的把数据提取到一个组内。
transaction summary表:事务摘要信息。
average trans...表:平均事务时间,查看标准方差。
添加度量图形:
右键选择add new item---add new graph---system resources
如果发现有问题,又分析不出问题,可以添加查看网页细分图
web page diagnostics下都是可以查看。
如:page download time breakdown表:可以查看每个组件在服务器内的时间值。
connection time:连接时间,组件与Web服务器建立初始连接的时间。
first buffer time:组件从HTTP请求到成功收到Web服务器第一次缓存的时间。
receive time:整个组件与Web服务器连接的时间。
SSL握手时间:建立SSL连接所用的时间(HTTPS)。
如:time to first buffer breakdown表:可以查看server time 和network time的时间
报告new report 点击 generate 生成报告,然后就可以保存了。
LR功能梳理:
vuser:关联:1.普通关联 2.关联数组---随机选择。事务。检查点。思考时间。集合点。
controller:负载生成器。性能测试场景。控制各种运行策略:IP欺骗,带宽模拟。
=======================================================
性能测试计划:
性能指标有多个站在用户和开发两个方面:运行程序占用,访问量,持续服务,相应时间
开发:涉及合理,安全,效率,回收,扩展,readme等
top:cpu:load average 5 15分钟负载(负载不能比CPU核数4倍还多)
负载阶段:规划、创建脚本、定义场景、执行场景和分析结果。
并发与并行、并发用户数和在线用户数、TPS和响应时间、点击数、吞吐量、资源使用率、PV和UV
CPU并行:真的同时执行,CPU多核同时进行任务。
CPU并发:不一定同时执行。因为有CPU有中断,所以感觉单核可以做多个任务,实际没有并行。
并发用户数:有效的负载用户。要一直操作。
在线用户数:包括操作和不操作用户。
transaction per second:每秒事物。每秒业务数。
相应时间:客户端+网络+服务器
点击数:发出请求数。
吞吐量:单位时间被处理的业务或者请求量。
资源使用率:%
PV:一个URL,访问量。
UV:一个用户,访问ip数量。
测试工具的协议才会造成负载!
通信协议:标准协议、自有协议
工具要有更新才有生命力,才学。
跨平台的工具才是好工具。
loadrunner jmeter Gatling IBM RPT was silk-performer
协议:Web SOAP FTP JDBC 等
选择协议:邮件协议:SATP\POP
问开发,经验,看项目文档,协议探测器(loadrunner自带)
选择协议,选择的是与压力模拟直接交互的中间件或者服务器,和后面的无关。再次强调,loadrunner录制只与协议有关,和操作界面关系不大。
安装LR注意要干净的系统,linux只支持负载生成器
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都列出来,所以看出所有的过程,更接近请求-响应的本质。高级部分:
会生成web_custom_request only。
建议第一次录制使用:HTML-based script中的A script containing explicit URLs only,可以分出块来判断协议交互。
注释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可以关联,如用户名关联密码。但是数据1和数据2下面的如何切割数据池必须两个一致,才能关联。
参数化会在保存目录内生成.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,那么一个用户就用一个数据。
sequential---once---所有用户都取即参数中的第一行值。
random---once---不同用户随机一次,以后都取此值。
unique---once---按照从上到下,有几个用户分配几个数。
unique---each occurrence---只能手工分配用户,给每个用户分配好X个参数后,在脚本中有参数的地方就用这几个。
unique---each iteration---若选择手工自配参数,那LR按照每用户几个参数分配,然后进行循环。
若选择自动分配,LR将按照用户数均分参数,剩余的参数不使用。
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并发的时候使用。
性能测试计划:
脚本开发的原则:简单、正确、高效
单用户循环一次,多次(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
启用controller,点击tools选择Create Controller Secenario。
可以选择Goal 或者 Manual,Manual可以选择多少个用户并发,选择负载生成器,建议虚拟机出一台专用负载机。
不管是否使用负载生成器,都要更改ip为实际ip,不能有localhost的ip。
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。
如果设置ip欺骗,lr必须用对应的ip欺骗的网卡,启用Enable IP Spoofer后LR会查看所有网卡内的ip,如果ip没有联通,那就会出现错误,无法连接网络的问题。
集合点
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
如果在controller内没有Diagnostics的更多组件配置,需要装Diagnostics,然后LR上需要装diagnostics plug in,和diagnostics做集成。具体你看diagnostics和LR的安装文档,但是LR11是自带一些,LR12没有再带。
set granularity 设置取点的间隔,可以增加点,或者减少点。而且取值为平均值。
view meansurement trends 查看趋势,就是把y轴去掉,然后把曲线重叠。
view raw data 可以取原始数据,然后做成excel表。点击后,在右侧会有折叠页。并且包含思考时间。导出后在excel内画图,更精确。
图标的合并
拐点上是不可接受,也就是角度很大,过陡;拐点下是可以接受,也就是角度很小。
合并需要x轴单位一致。点击图表右键的Merge Graphs
Overlay 共享一个x轴
Tile 共享一个x轴,其中一个在上面。
Correlate 取消两个图表的x轴,并把两个y轴作为数轴x和y轴。方便查看拐点的图表。
右键auto correlate,可以自动correlate图表,对图表截图后合并。方便查看相关性的参数,了解如果改变环境,需要增加那些硬件。可以查看部分增加用户的时间段内,增加用户后其他参数的变化。可以查看相关性。correlation match 是两个数据之前的相关度,100%或者很低。
如果生成的数据太突兀,可以慢慢的把ramp up和ramp down变慢,并且把时间设计合理。可以得到合理的数据。
前端性能指标:
前端分析方面:前端网络、前端浏览器加载、js执行效率。
浏览器加载是否压缩,压缩图片,压缩js,压缩响应,代码压缩等,合并多个相同的资源,预加载,异步加载,减少frame框,减少缓存。
1.响应时间,越少越好
2.相应的吞吐量thought,每秒服务器响应的大小,直接关联服务器的带宽,查看是否需要扩容或者减少。如果
服务器的带宽再除以虚拟的人数就是客户端的带宽。如果是100M/s,那么除以8就是12.5M/s是实际监控的带宽。
3.TPS 每秒事务数,可以估计设计性能需求,比并发更靠谱。或者TPM每分钟事务数,TPH每小时事务数。
4.HPS每秒点击数,作用不大。尽量减少越好。数量越多越服务器好。
后端服务器性能指标:
CPU:CPU使用率 processor time,CPU队列 processor queue 2*内核数,如果使用率100%,服务器卡,但是可以继续运行。
带宽:每秒接收或发送的数量, 下载或上传的带宽/8 bytes received和bytes sent
内存:内存使用率,内存的页交换频率,page/sec,越低越好,与磁盘的交换。如果使用率100%,服务器会出现主要瓶颈和崩溃。
虚拟内存:利用硬盘充当内存,内存和硬盘价格差100倍,内存和硬盘的速度也是差100倍。
磁盘:硬盘使用率,硬盘队列长度,logicalDisk下的disk time硬盘的使用率,avg disk queue length
重点优化就是缓存机制和线程机制,包括CPU,内存,硬盘都是有缓存机制,数据库的线程机制。
线程池:用于管理多线程的机制,线程主要消耗CPU的资源。主要的是CPU的极限,CPU资源是有限的。而且和动态影响有很大关系,比如增加思考时间,可以减缓线程的负载。三层架构中,增加服务器的线程效果一般,同时也要查看CPU的资源和服务器与数据的带宽,并增加数据库的线程。也就是说调小服务器的线程一定减少服务,但是调高服务器的线程不一定能增加服务。
性能测试方案
对比两个软件的性能,保证硬件、软件、网络等一样。
1.搭建服务器,安装不同软件,开发LR脚本。
2.测试对象
3.测试环境
4.被测模块
5.性能测试脚本
6.性能场景
7.指标分析
8.其他
目录:1引言:1.1背景 1.2编写目的
2参考文档 3测试目的 4测试范围 4.1测试对象 4.2测试特性 4.3不需要测试的特性
5测试模块准侧 6测试方法 7测试暑促 8测试计划 8.1总体计划 8.2详细计划人员安排 9测试环境 10测试风险 11测试提供资源
不知道并发多少虚拟用户是合理的,网上找到的并发用户的计算方法,是错误的,无参考价值。
从tps出发,增加1.2倍,通过ramp up 来预测,最大并发,然后再反算,是否满足tps的需求。
如果是新系统只能先尽力优化,然后随时监控,提前发现瓶颈。
分析报告:
关联虚拟用户和响应时间,通过虚拟用户的增加,响应时间是否也随着变化。如果没有,那就是没有到达瓶颈,无负载。可以得到瓶颈的一个范围,50-55。
两次不同虚拟用户的结果可以同时对比。
cross with result---可以添加多个测试结果。
关联虚拟用户和CPU使用率,通过虚拟用户的增加,CPU利用率是否也随着变化。如果没有到达最高,那就是没有达到瓶颈,无负载。
找到最大值,再找为最佳用户数。
多个测试结果,肯定会有一张图有明显的全面优势,那就是优势图,并且会有几张为相同硬件的趋势图,会全面相同,证明测试有效性。
性能测试的报告:
1.性能测试结果 2.系统测试摘要 3.测试结果分析 4.改善建议 5.总结
可以生成报告,可以参考。
在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查询帮助、回表、联合索引,
测试报告:
新建脚本时,可以选择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/