对Flex4.1 Web应用进行性能测试(loadrunner)

上一篇 / 下一篇  2011-11-23 10:24:32

这是一次简单的性能测试实战,但其中包含了许多性能测试要点,写出来是为了理清思路和分享讨论

废话少说,直接上菜~

【测试工具】loadrunner9.52

【被测系统说明】以Flex为前端应用,JAVA为后台处理的B/S系统

【性能测试目标】

1.测试系统常用功能在极大数据量下的响应时间以及查询效率

2.系统定时自动刷新数据,多用户并发的情况下,服务器资源利用率与响应时间

3.负载测试,找出系统可以承受的极限数据量和并发量

4.压力测试,以接近极限数据量和并发量的情况下,长时间运行

5.数据量极大的前提下,报表统计的效率

============什么性能指标获取,与开发、配置管理员协调,其实这部分是整个性能测试的指导,但本文只是想与大家讨论一下整个性能测试的一个流程与其中思想,所以这里就不细说了。

【测试网络拓扑结构】

===========说明:被测系统服务器上只运行web应用,数据库其他平台在其他系统服务器上,这里只用一个图标表示其他系统

【测试脚本录制】

我们项目是Flex技术作为前端开发的应用,所以我们需要启动loadrunner的Flex/Web脚本。
录制之前,有必要说一下Flex的交互机制。浏览器作为客户端与服务器之间交互的媒介是amf,amf将服务器返回的数据编译后,到客户端进行解析,而本项目服务器端返回的数据解析后都是xml。录制完成后,让我们看一下生成的部分代码以及服务器返回的xml数据

loadrunner代码:

vuser_init() {

web_url("OMM", "URL=http://162.0.0.107:9180/OMM", "Resource=0", "RecContentType=text/html", "Referer=", "Snapshot=t197.inf", "Mode=HTTP", LAST);

web_url("swfobject.js", "URL=http://162.0.0.107:9180/OMM/swfobject.js", "Resource=1", "RecContentType=text/javascript", "Referer=http://162.0.0.107:9180/OMM/", "Snapshot=t198.inf", LAST);

web_add_header("x-flash-version", "10,3,181,14"); web_url("OMM.swf", "URL=http://162.0.0.107:9180/OMM/OMM.swf", "Resource=1", "RecContentType=application/x-shockwave-flash", "Referer=http://162.0.0.107:9180/OMM/", "Snapshot=t199.inf", LAST); web_add_auto_header("x-flash-version", "10,3,181,14");

flex_amf_call( "AMF3_call", "Gateway=http://162.0.0.107:9180/OMM/messagebroker/amf", "Snapshot=t200.inf", "ResponseParameter=amf_dsid", MESSAGE, "Method=null", "TargetObjectId=/1", BEGIN_ARGUMENTS, "\n " "\n5092B71C-A982-EC3C-979C-C5000BD59ED4\n " "0\n0\n\n " "\nDSMessagingVersion\n1\n " "\n\nDSId\nnil" "\n\n\n \n\n\n " "\n0.75\n" "12\n\n16\n0\n " "\n\n\n " "false\nfalse\n " "\n\n \n" "\n5\n" "", END_ARGUMENTS, LAST);

lr_xml_get_values("XML={amf_dsid}", "FastQuery=/AMFPacket/Messages/Message/AMF3/object-externalizable-custom/flex.messaging.messages.AcknowledgeMessageExt/flex.messaging.io.amf.ASObject/map/string[3]", "ValueParam=dsid", LAST);

flex_amf_call( "AMF3_call_1", "Gateway=http://162.0.0.107:9180/OMM/messagebroker/amf;jsessionid=E2D06A0CD5542BA5FF834EEC4B179851", "Snapshot=t201.inf", MESSAGE, "Method=null", "TargetObjectId=/1", BEGIN_ARGUMENTS, "\n " "HttpSessionService\n" "D74084C6-F8C9-2996-68E6-C5000B0ACA00\n0\n " "0\n\n\n" "DSId\n{dsid}\n " "\n\nDSEndpoint\n" "my-amf\n\n\ngetSession" "\n\nOMM_USER_SESSION\n" "\n" "", END_ARGUMENTS, LAST);

.....}

解析后的的服务器响应

vuser_init.c(36): AMF response message received. The following XML describes the message content:
vuser_init.c(36): 
<AMFPacket AMF_version="3">
<AMFHeaders>
<AMFHeader name="AppendToGatewayUrl" must_understand="true">
<string>;jsessionid=C234853CAA9C12E2C2F93D17B2CD880A</string>
</AMFHeader>
</AMFHeaders>
<Messages>
<Message method="/1/onResult" target="">
<AMF3>

<object-externalizable-custom>

<flex.messaging.messages.AcknowledgeMessageExt>

<byte>-88</byte>

<byte>3</byte>

<flex.messaging.io.amf.ASObject serialization="custom">

<unserializable-parents/>

<map>

<default>

<loadFactor>0.75</loadFactor>

<threshold>12</threshold>

</default>

<int>16</int>

<int>2</int>

<string>DSMessagingVersion</string>

<double>1.0</double>

<string>DSId</string>

<string>870BCE6D-4408-EB78-FBBF-BD16FC2038AA</string>

</map>

<flex.messaging.io.amf.ASObject>

<default>

<inHashCode>false</inHashCode>

<inToString>false</inToString>

</default>

</flex.messaging.io.amf.ASObject>

</flex.messaging.io.amf.ASObject>

<long>1322101201796</long>

<byte-array>hwvObUQf7Lg4fqUpf+9AHg==</byte-array>

<byte-array>hwvObUQuc6aXE9CvnjwC3A==</byte-array>

<byte>2</byte>

<byte-array>UJK3HKmC7DyXnMUAC9We1A==</byte-array>

<byte>0</byte>

</flex.messaging.messages.AcknowledgeMessageExt>

</object-externalizable-custom>

</AMF3>

</Message>

</Messages>

</AMFPacket>

vuser_init.c(36): FLEX AMF Call ("AMF3_call") was successful

回放前,先设置一下输出日志的内容,Vuser-->Run-time Settings-->log-->log messages at the detail level of-->Extended log中勾选Data returned by server

注意:这个日志选项会带来一些麻烦,如果服务器返回的是一个.swf页面的话,回放时,loadrunner解析返回输出数据的速度很慢,所以如果代码中有请求.swf资源,最好先注释掉这段代码,待调试结束后,再将代码还原

回放时,在flex_amf_call("AMF3_call_1"...)处会发生错误,这说明我们需要对提交给服务器数据的某个值进行参数化,我们翻回来看一下flex_amf_call("AMF3_call"...)这段对应的回放日志

<AMFPacket AMF_version="3">

<AMFHeaders/>

<Messages>

<Message method="/1/onStatus" target="">

<AMF3>

<object-externalizable-custom>

<flex.messaging.messages.ErrorMessage>

<destination>HttpSessionService</destination>

<messageId>8736B554-CD0D-900E-199C-BBBA1D663CAC</messageId>

<timestamp>1322102353437</timestamp>

<timeToLive>0</timeToLive>

<correlationId>F748F4F4-310A-4298-710C-D36D9D9AA8B7</correlationId>

<faultCode>Server.Processing.DuplicateSessionDetected</faultCode>

<faultString>Detected duplicate HTTP-based FlexSessions, generally due to the remote host disabling session cookies. Session cookies must be enabled to manage the client connection correctly.</faultString>

</flex.messaging.messages.ErrorMessage>

</object-externalizable-custom>

</AMF3>

</Message>

</Messages>

</AMFPacket>

Action.c(61): Error: Server returned error for message #1 : description="AMF call returned an error, described in XML seen in extended log" 

从日志中可以看到,出错的原因faultCode以及这个错误的解释faultString,correlationId则表示是哪个请求造成了报错,我首先去查了faultCode这个报错是什么原因造成的,结果收获不大,在51坛子里找到几篇同样问题的文章,其中有一个已经解决的了问题,但没有说明解决办法。只知道需要做参数化,关联。接着通过correlationId找到了提交请求的代码

想看回放时,loadrunner提交的数据和服务器响应,可以进入Tree视图--snapshot页签内查看repaly时,loadrunner的request和服务器响应reponse

?xml version="1.0" encoding="UTF-8" ?>

<AMFPacket AMF_version="3">

<AMFHeaders />

<Messages>

<Message method="null" target="/1">

<Arguments>

<Argument>

<AMF3>

<object-externalizable-custom>

<flex.messaging.messages.RemotingMessage>

<destination>HttpSessionService</destination>

<messageId>F748F4F4-310A-4298-710C-D36D9D9AA8B7</messageId>

<timestamp>0</timestamp>

<timeToLive>0</timeToLive>

<headers>

<entry>

<string>DSId</string>

<string>87307160-021B-F330-799A-97CD0AF390DC</string>

</entry>

<entry>

<string>DSEndpoint</string>

<string>my-amf</string>

</entry>

</headers>

<operation>getSession</operation>

<parameters>

<string>OMM_USER_SESSION</string>

</parameters>

</flex.messaging.messages.RemotingMessage>

</object-externalizable-custom>

</AMF3>

</Argument>

</Arguments>

</Message>

</Messages>

</AMFPacket>

请求中有DSId,这个立刻引起了我的注意;因为在DSID下面有getSession字样,这个DSId可能就是flex的SeesionId,下面我们就开始进行参数化;

先整理一下思路,问题:当flex_amf_call("AMF_call_1"...)提交请求时,服务器返回了错误,错误的原因是提交的DSId不正确。那么这个正确的DSId应该去哪里获取呢?这时,我注意到flex_amf_call("AMF_call"...),从回放日志中看出是它请求服务器授予loadrunner一个DSId,那么服务器返回给它的数据中就应该包含DSId的值;有了这个思路,接下来就是如何将服务器返回的DSId进行参数化。flex应用的参数化比较不同,它使用了loadrunner函数lr_xml_get_values,这个函数是利用xpath查找服务器返回数据中节点的值,将这个值保存到一个变量中;

lr_xml_get_values(
"XML={amf_dsid}",
"FastQuery=/AMFPacket/Messages/Message/AMF3/object-externalizable-custom/flex.messaging.messages.AcknowledgeMessageExt/flex.messaging.io.amf.ASObject/map/string[3]",
"ValueParam=dsid",
LAST);

这个函数有3个参数,XML={amf_dsid}代表要查找的数据源,FastQuery=...代表xpath(也就是数据所在的节点路径),ValueParam=dsid则代表将查找出的值保存到dsid这个变量中,我们将这个函数放到flex_amf_call("AMF_call"...)的后面,这样在服务器发出获取DSId的请求,服务器返回DSId后,我们的函数就会将这个值赋给dsid这个变量,我们用dsid这个变量将所有代码中出现DSId值得地方全部替换为{dsid},就完成了参数化;

函数的参数XML={amf_dsid},数据源{amf_dsid}是由测试者自己设置的,设置方法为:在Tree视图的snapshot中,在左侧列表中找到AMF_call这项,双击后在弹出的对话框中有Response Parameter这项,这里就是设置数据源名称的地方,填写后保存即可。例如:我填写的是amf_dsid,那么在函数中XML={amf_dsid}
至此,flex的脚本录制就应该没有什么问题了。下一节,会写怎么设计loadrunner的测试场景,对应的loadrunner工具loadrunner controller。


TAG:

aslandhu的新窝:http://www.wuchuanhu.cn/ 引用 删除 aslandhu   /   2011-11-24 10:34:11
呵呵,AMF其实跟XML差不多,只是它是一个二进制的XML数据流,当然我的表述可能也不准确,不过他们之间确实是有区别的,AMF毕竟是adobe为Flex定制的交互协议。此外,Flex应用也不一定会用AMF协议,也有可能会用HTTP或者SOAP,所以针对不同的Flex应用,可能性能测试选择协议上需要根据具体实现来考虑。你这篇文章很不错,期待你对Flex性能测试的更多研究文章。

原帖由水煮肉片于2011-11-24 10:10:49发表
原帖由aslandhu于2011-11-24 09:05:03发表
"浏览器作为客户端与服务器之间交互的媒介是xml报文,其.
水煮肉片~麻辣人生 引用 删除 水煮肉片   /   2011-11-24 10:10:49
原帖由aslandhu于2011-11-24 09:05:03发表
"浏览器作为客户端与服务器之间交互的媒介是xml报文,其实就是一个xml数据流"   ??AMF数据流.

loadrunner截获的服务器返回数据解析后,确实是一个xml格式的报文,至于amf到底是什么,这个我确实不清楚,具体的服务器返回我在上面贴出来,你可以看下,刚才查了下,amf是将服务器端返回的xml等数据格式编译成amf格式的二进制数据流,我的表述出现了问题,应当写【这个amf返回的其实是一个xml】而不是amf本身是xml,谢谢你的指正:),另附amf的解释,供其他被我误导的人看看http://hi.baidu.com/half_cup_coffee/blog/item/3abd5b8828192f90a5c27240.html
aslandhu的新窝:http://www.wuchuanhu.cn/ 引用 删除 aslandhu   /   2011-11-24 09:05:03
"浏览器作为客户端与服务器之间交互的媒介是xml报文,其实就是一个xml数据流"   ??AMF数据流是XML?LZ,开玩笑还是我孤陋寡闻啊,呵呵。
aslandhu的新窝:http://www.wuchuanhu.cn/ 引用 删除 aslandhu   /   2011-11-24 09:04:54
3
 

评分:0

我来说两句

Open Toolbar