基于AJAX架构长时间事务脚本关联的探索

1. 项目背景

项目名称:贵州电网《用户供电可靠性综合管理信息系统》

测试功能点:中压指标统计

问题现象描述:

  • ①脚本在Loadrunner 11下正确完成录制后,运行未经处理的原始脚本,可以正确返回查询结果;
  • ②将脚本中的查询时间段更改后,再次运行脚本,可以返回查询结果,但是查询结果仍然为录制脚本时返回的结果,结果中的查询时间段没有改变;
  • ③多次手工在浏览器上进行“执行计算”操作,对比查询结果,发现结果项中存在字段“统计任务ID”,该值呈递增趋势,即每操作一次,ID值增长1;因此可以将其理解为该查询事务的流水号。
  • ④在脚本中分析“统计任务ID”,确定该值需要进行动态关联;对该字段正确地完成动态关联后,再次运行脚本,在Replay Log中显示该字段成功替换为新的流水号,且无执行失败的事务项;但是查看Test Results发现,记录信息没有找到,查询结果为空;多次重复运行脚本,仍然存在同样的问题。

2. 问题分析

对比问题现象描述的②和④,可以提炼出如下三点:

  • 对字段“统计任务ID”关联操作之前,可以返回查询结果,只是返回的结果仍然为录制脚本时返回的结果,更改查询条件后查询结果不变;
  • “统计任务ID”在脚本中正确地完成了关联操作;
  • 对字段“统计任务ID”关联操作之后,无法返回查询结果。

进一步分析可得:查询结果可能与“统计任务ID”相关联。

那么,为什么脚本执行时采用历史“统计任务ID”可以得到结果,而采用服务器最新返回至客户端的“统计任务ID”就无法得到查询结果呢?

针对此问题,进行如下试验。

 

3. 解决方案的探索过程

3.1 试验1

既然Loadrunner无法使用服务器最新返回至客户端的“统计任务ID”取回查询结果,那么如果将脚本中的“统计任务ID”替换为其它历史ID值(不同于录制脚本时的ID值),结果会怎样呢?

比如,当前最近一次服务器返回至客户端的“统计任务ID”为93289,那么就将脚本中的“统计任务ID”直接全部替换为93289(如果进行动态关联的话,脚本运行时ID值将会变为93290),重新执行脚本完毕后,在Test Results中发现成功查询到结果记录,且该记录中的查询时间段不再是录制脚本时设置的时间段,而是脚本中更改后的时间段。

多次更改“统计任务ID”后执行脚本,发现如下两点现象:

  • “统计任务ID”设置为历史ID值(假如最近一次服务器返回的“统计任务ID”为93289,那么历史ID就是指小于等于93289的值)时,均可返回查询结果;
  • “统计任务ID”设置为非历史ID值(假如最近一次服务器返回的“统计任务ID”为93289,那么非历史ID就是指大于等于93290的值)时,查询结果均为空。

根据这两点可以推断得出:查询结果确实与“统计任务ID”相关联,Loadrunner执行脚本时会根据脚本中的“统计任务ID”取回对应的记录。

由此我们进一步思考:当脚本中“统计任务ID”设置得大于服务器最近一次返回的ID值时,无法返回查询结果,这的确情有可原,毕竟在服务器端该次计算还未执行;但是为什么脚本中对“统计任务ID”进行动态关联后仍然无法取回查询结果呢?

更细致地对该事务进行分析可知,该事务脚本执行的时候分为三步:

  • ①客户端(Loadrunner中的脚本)设置查询条件后,向服务器端提交查询请求;
  • ②服务器接收该次查询请求,进行执行查询计算,并向客户端返回该次查询的流水号;
  • ③客户端(Loadrunner中的脚本)用服务器返回的流水号向服务器请求查询结果。

显然,步骤①是不会有问题的,因为已经成功取到过查询结果。那么,问题只可能出现在步骤②和步骤③中。

在此,可以针对步骤②和步骤③分别做出如下两个猜想:

  • 猜想1:利用Loadrunner执行脚本的时候,服务器对脚本执行过程中的请求响应不正确,造成查询失败,从而没能返回查询结果。
  • 猜想2:利用Loadrunner执行脚本的时候,服务器对脚本执行过程中的请求正确地进行了响应,并查询得到了结果,只是客户端在后续的脚本执行中没能用流水号取回查询结果。

针对猜想1和猜想2,分别进行如下的试验2和试验3。

3.2 试验2

针对猜想1,采用如下步骤对其验证。

步骤一、在该事务的测试脚本中,将“统计任务ID”字段正确地进行动态关联;

步骤二、执行脚本后,得到服务器最新返回的“统计任务ID”值,假设为93290;当然,该次查询结果和以前一样,仍然无返回结果;

步骤三、将该事务测试脚本中的“统计任务ID”字段全部替换为93290,再次执行脚本,查看查询结果,发现该次成功返回查询结果。

根据试验2可以得出:利用Loadrunner执行脚本的时候,服务器对脚本执行过程中的请求正确地进行了响应,并查询得到了结果。从而猜想1不成立。

3.3 试验3

那么,问题出现原因便聚焦到:客户端(Loadrunner)在后续的脚本执行中没能用流水号取回查询结果。

为了了解其中的原因,我们从脚本入手,看看从服务器开始计算到服务器返回查询结果期间,客户端与服务器都做了哪些交互。

比对Test Results和脚本,可以得出在服务器开始计算之后和服务器返回查询结果界面之前,录制得到的脚本为:

  • web_custom_request("TjZyService.invokeCompute") //服务器开始执行计算
  • web_custom_request("TjZyTaskService.returnKHMC")
  • web_custom_request("TjZyTaskService.returnKHMC_2")
  • web_custom_request("TjZyTaskService.returnKHMC_3")
  • 。。。
  • web_custom_request("TjZyTaskService.returnKHMC_34")
  • web_url("TjZyAction.do")//服务器返回查询结果页面

观察这些脚本可知,在服务器开始计算之后和服务器返回查询结果界面之前,客户端与服务器之间反复进行同样的交互,即web_custom_request("TjZyTaskService.returnKHMC"),该函数的格式如下图所示:

clip_image001

在各个函数中,变化的只有c0-id,且变化无规律;在Generation Log中查找该值,发现这个值是每次由客户端请求至服务器的,且在后面的脚本中没有再用到该值。因此可以断定该值无需关注。

那么,在该事务中,这些函数的作用是什么呢?

为了寻找该问题的答案,在同样的条件下重复多次录制脚本,发现每次录制得到的脚本中web_custom_request("TjZyTaskService.returnKHMC")的数目不尽相同。

这说明该函数可多可少,并非每一个都是必要的。那么,该函数的个数到底是什么因素决定的呢?什么时候会多一些,而什么时候会少一些呢?

另外,在执行该脚本的时候,发现另外一个问题。在实际手动查询的时候,整个流程的时间很长,大概六七分钟;而运行修改完毕的脚本时,总的运行时间大概不到三分钟,远远少于手动查询时间。

众所周知,Loadrunner在运行脚本的时候,是模拟人的手工操作,对于服务器来说应该是一样的,因此理论上两者耗费的查询时间也应该是大致相同的。但是现在Loadrunner执行脚本的时间远小于手动查询时间,这会不会就是造成Loadrunner最终没有查询得到结果的原因呢?

还有,在该事务的执行过程中,需要执行这么长的时间,那这期间客户端和服务器之间是怎样交互的呢?为此,通过HttpWatch工具监控该事务执行过程,发现该事务的Time Chart如下图所示。

clip_image002

由上图所示,该事务执行过程中,各个web_custom_request("TjZyTaskService.returnKHMC")函数之间的时间间隔基本上是恒定的,两次请求之间大概相差5秒钟,即客户端每隔5秒向服务器发送一次请求。

 

4. 结论

经过以上的分析,不难得出该问题出现的原因:在该事务执行的过程中,服务器需要较长的时间对客户端的请求进行计算。而利用浏览器和Loadrunner进行查询请求时之所以会有不同的结果,是在于:

  • 通过浏览器向服务器提交查询请求后,浏览器前台一直显示“正在查询”的页面,而后台则会定期地(每隔五秒)向服务器询问查询结果,直到服务器完成计算为止,浏览器才能取回查询结果并在页面上显示出来。
  • Loadrunner执行未关联“统计任务ID”的脚本(“统计任务ID”设置为历史ID值)时,由于该次查询服务器之前已经执行过,因此服务器无需再次长时间计算,便能直接将该流水号的查询结果返回至Loadrunner。
  • Loadrunner执行动态关联后的脚本的时候,没有停顿,当所有的脚本执行完毕后,服务器还未计算出查询结果,因此Loadrunner获得的查询结果为空。

5. 结论验证

由之前分析得到的结论可知,只要Loadrunner执行脚本的时候能给服务器足够的执行时间,那么Loadrunner在脚本执行完毕后就能得到查询结果。

因此,尝试删除多余的web_custom_request("TjZyTaskService.returnKHMC"),只留一个函数,然后在该函数之后增加思考时间lr_think_time(400);在Run-Time Settings中启用Think Time,重新运行动态关联“统计任务ID”字段后的脚本。

脚本执行完毕后,查看Test Results,可以看到,该次执行已经成功地取回查询结果。

 

6. 最终解决方案

在脚本中设置一个固定的思考时间lr_think_time(400)虽然可以解决脚本执行后无法取回查询结果的问题,但是这会造成测试结果无意义,因为我们无法得到该查询事务的实际耗费的时间。

为此,我们可以设计一个检查点,模拟浏览器定期地查询服务器状态,每隔五秒执行一次web_custom_request("TjZyTaskService.returnKHMC"),然后利用检查点函数查看该函数的返回关键词,判断浏览器是否完成计算操作;具体脚本的实现如下图所示。

clip_image001[4]

转载于:https://www.cnblogs.com/stleo/articles/2410885.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值