【笔记】LR响应时间

 事务:是指在客户端做一种或多种的业务所需要的操作集。

事务响应时间:是通过记录用户请求的开始时间和服务器返回内容到客户时间的差值来计算用户响应时间。

响应时间是服务器返回和用户请求之间的时间差,那么得到这个时间就够了吗?

例如:我们现在有一场跑步比赛,当我们完成比赛后,我们可以得到每位运动员跑完整个比赛所需要消耗的时间,我们现在要分析谁起跑好,谁冲刺好,能分析出来吗?

           答案是不能,确实我们得到了最重要的完成比赛的响应时间,我们知道了结果这对我们分析,优化几乎没有作用。我们只知道了结果而不知道过程。

响应时间的组成

对于软件来说我们得到的系统响应时间也是非常多的部分组成的,一般来说我们的响应时间由以下几个部分组成:

N1:客服端发出请求首先通过网络来到web server上,消耗时间为N1。

N2:web server将处理后的请求发送给App Server,消耗时间为N2。

N3:App Server将操作数据指令发送给data base,消耗时间为N3。

N4:Data base将查询结果数据发送回App Server,消耗时间为N4。

N5:App Server将处理页面发给web server,消耗时间为N5。

N6:最后Web Server将HTML转发到客户端,消耗时间为N6。

WT:Web 服务器处理时间

AT:App服务器处理时间

DT:Data base服务器处理时间。

 除了上面的时间以外,我们还要考虑网络延迟的问题。

响应时间=网络延迟时间+WT+AT+DT+(N1+N2+N3)+(N4+N5+N6)+WT+AT+DT

细分会发现响应时间的组成是非常复杂的,当性能出现问题,我们想要定位到具体的代码级别是比较困难的。

所以最终的事务响应时间是:客户请求发送开始计时到服务器完全返回所有请求的差。

LR只能对自己发出的请求和服务器返回的内容做,也就是说LR能够分析的时间为客服端到web服务器的时间N1和web服务器返回到客户的时间N6。

这些时间主要和网络速度有关,我们可以用一个LR的名称来解释,叫做breakdown时间。

也就是说LR可以分析的时间只有客户端到web server之间的时间细分,后面从web server到app server 到DB server的时间我们只能得到一个总和。

添加事务

通过事务监控响应时间

我们需要做的就是在请求的发出前添加一个事务开始的计数器,在请求结束的地方添加事务结束的计数器,LR会帮助我们自动计算时间差。

通过工具栏上的事务按钮即可完成事务的添加:

插入事务的开始:

添加事务的名称。

添加事务结束。

【注意】这里的事务的开始和事务结束名称需要配对。即同一事务的开始和结束的事务名称应相同。

  事物状态

  Transaction Status:事务状态,默认值为LR_AUTO来作为事务的状态的,结果为PASS/FAIL/STOP

                                 LR_PASS指事务是以pass状态通过的,说明该事务做了该做的正确的事情,并且记录下了对应的时间,这个时间就是做这件事情所需要消耗的响应时间。

                                 LR_FAIL指事务以FAIL状态结束,该事务是一个失败的事务,没有完成事务脚本应该达到的应有效果,得到的时间不是正确操作的时间,这个时间在后期的统计中将被独立统计。

                                 LR_STOP将事务以stop状态停止。

   事务的PASS和FAIL状态会在常见的对应计数器中记录通过的次数和事务的具体时间。方便我们后期分析该事务的吞吐量以及响应时间的变化情况。

事物和子事务

在LR中我们可以通过事务来完成一组操作的响应时间监控,如果我们想监控一个事物中的某一步操作的响应时间,我们就需要使用子事务来完成:

Lr_start_sub_transaction("子事务名","父事务名")

Lr_end_sub_transaction("子事务名","子事务状态")

虽然子事务和父事务很像,但是父事务支持的很多函数,在子事务中都无法实现,所以需酌情考虑。

例如:我们需要做一个登陆的事务,想知道打开登陆页面和登陆操作的时间,我们可以使用子事务。

Lr_start_transaction("login");

Lr_start_sub_transaction("loginpage","login")

//打开登陆页面

Lr_end_sub_transaction("loginpage","LR_AUTO")

Lr_start_sub_transaction("submitlogin","login")

//提交登陆表单

Lr_end_sub_transaction("submitlogin","LR_AUTO")

Lr_end_transaction("login",LR_AUTO);

这样我们就可以等到3个事务的时间。

事务相关的函数

lr_get_transaction_duration()  // 获得对应事务达到该函数运行位置持续的时间。

lr_get_transaction_wasted_time()  // 获得对应事务到达该函数运行位置时的wasted时间

lr_wasted_time() // 为一个事务添加wasted时间

lr_stop_transaction() // 将一个事务暂停,该函数后的操作都不会计入事务时间

lr_resume_transaction() // 将暂停的事务恢复

一个事务的时间是指duration时间,事务会完全记录下从事务开始到事务结束之间的时间差,那么事务的时间能真实的反映业务操作的时间吗?

不能,就好像我们人用手按秒表来记录短跑时间一样,得出的时间并不是完全的正确,这里存在了人观察的误差和按秒表的误差。对于一个事务的duration时间来说。一般由4部分组成:

1、事务中业务操作时间

2、事务自身的时间误差

   指运行事务自身也是需要花费时间的,事务中哪怕没有操作。这个也是需要时间的,不过这个时间一般在百分之1秒左右,所有我们可以忽略。

3、think time

    think time 是LR提供的一种模拟用户等待的方式,通过函数LR_think_time()实现,在函数内写入对应的时间(单位是秒),在场景运行时脚本运行到该函数就会等待相应的时间。

【注意】①、在vugen中,回放think time默认关闭。think time在我们做性能测试的时候需要打开,只有这样我们的每个虚拟用户才是真正的按照用户的操作速度来完成请求,我们才能得到真实情况

             下的系统数据,如果我们不打开think time我们在测试理论下的一些峰值数据。

             ②、如果think time在事务中,会被算在事务的时间内。但是在Analysis中可以设置扣除。

4、wasted time

我们在使用事务的时候,经常会看到在事物日志中有wasted time,wasted time是指事务中应该扣除的由于其它原因导致的时间浪费。默认情况下LR会将自身脚本运行导致的时间浪费自动计入wasted time,例如关联函数、检查点函数等。

除了脚本自身浪费时间外,我们使用c语言等外部接口做处理所消耗的时间也会影响事务的时间。而这个时间LR无法自身处理。这种情况下我们就需要人为的计算第三方时间开销。并且将这个开销的时间记入wasted time中。

例如:

Action()

{

           int i,baselter=100;

           char dude[1000];

           merc_timer_handle_t timer; //检查动作的总运行时间
           lr_start_transaction("Demo");

           timer=lr_start_timer();

           for(i=0;i<=baselter*1000;i++){

           sprintf(dude,"this is the way we waste time in a script=%d",i)

            }

            wasteTime=lr_end_timer(timer);

            lr_wasted_time(wasteTime*1000);

            lr_end_transaction("Demo",LR_AUTO);

            return 0;

}

Lr_start_timer()是一个lr自带的时间计数器。它和lr_end_time()形成对应,能够返回这连个函数直接的时间差。

总结:为了确保响应数据的正确,我们需要扣除在脚本自身运行的时间消耗,事务中尽量避免出现非请求的处理内容,如果无法避免请使用lr_wasted_time()函数将多余的时间开销扣除。

例如:计算密钥是很消耗时间的,那么我们可以使用timer这个变量来记录的时间。并将这个时间从整个事务中扣除。

merc_timer_handle_t timer;

lr_start_transaction("Demo");

timer=lr_start_timer();   

//计算密钥 wasteTime=lr_end_timer(timer); lr_wasted_time(wasteTime*1000); lr_end_transaction("Demo",LR_AUTO);

  

   手工事务 

       前面都是使用LR_AUTO来自动判断事务状态的。现在我们在做一个脚本,看看LR是如何自动判断状态的:

录制一个注册用户的脚本,在提交注册表单处添加事务开始及结束,然后回放脚本。虽然回放脚本注册用户是失败的(该用户已经存在)但是事务还是pass状态下完成了,我们会发现

事务的duration时间短了很多。正常情况下注册一个一般都要2秒,现在只需要0.3秒。这是因为服务器判断到该用户已经存在后,就没有了数据插入的操作,直接返回错误页面,这个0.3秒

是系统处理错误的时间而不是注册用户所需要的时间。

        LR_AUTO是根据服务器的返回状态来决定事务是以LR_PASS状态通过还是以LR_FAIL结束,只要服务器把页面返回,那么事务就会认为我请求发出去成功了,服务器看懂了我的请求

也给我返回了内容,自然事务是PASS状态了。

       这样由于事务自动判断的错误,导致虽然我们的操作是失败的,但得到了一个响应时间,并且这个响应时间又没有正确的反映出做这件事情真正的时间,导致我们性能测试得到的分析数据错误。

对于这种情况我们就需要手工来判断操作是否成功。我们可以通过web_reg_fing()检查点函数来检查页面是否返回正确,然后通过rowcount的参数值来进行事物的状态判断,做到我们的智能判断事务

结果。

        例如:我们检查点函数的rowcount是保存在参数loginst中,那么事务的状态就应该这样判断的:

lr_start_transaction("login");

web_reg_find("Search=Body",

     "SaveCount=loginst",

     "Text=登陆失败",

      LAST);

//登陆请求

if(atoi(lr_eval_string("{loginst}")>=1))
      lr_end_transaction("login",LR_FAIL);

else

lr_end_transaction("login",LR_PASS);

 代码解释:

通过检查点来检查登陆后页面是不是存在“登陆失败”这样的内容,如果存在那么loginst的值就大于等于1。

注意,参数不能和值直接进行比较,我们要先通过lr_eval_string()转化成字符串,然后再通过atoi()函数转化成整数,这样才能和1比较。

原文地址:https://www.cnblogs.com/benpao1314/p/10156700.html