发现问题的应用场景
C/S结构程序,请求响应采用异步机制。即客户端发送一个请求后不是一直等待这个结果,客户端将请求存放在请求队列并获得一个JOBID,服务器运行后将运行结果存放在响应队列,客户端定时查看响应队列,根据JOBID定时从响应队列中获取结果。因此带来的测试问题是受服务器状态影响,客户端获取结果的次数不固定。
测试脚本示例
lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=localhost:8080", LrsLastArg);
lrs_send("socket0", "buf56", LrsLastArg);
lrs_receive("socket0", "buf57", LrsLastArg);
GetJobID();
do{
lr_think_time(0.3);
lrs_send("socket0", "buf58", LrsLastArg);
lrs_receive("socket0", "buf59", LrsLastArg);
}while(!CheckStatus());
其中buf56、57是发送请求,buf58、59是循环去获取结果并检查返回的标志位,若仍没有结果返回则在一定时间后循环获取结果,因此请求数不固定。
LR提示socket异常
当我用lrs_create_socket创建连接之后,当这个socket连接的请求次数达到100次后,这个连接就不可用了,必须close后再重新create。LoadRunner提示错误:Error : socket0 - Software caused connection abort. Error code : 10053.
问题验证
一开始认为是LoadRunner对Socket的支持问题,因为同样的测试方式在Rational Robot中可以通过。于是做了最简单的一个试验:
1、用socket方式录制访问某个网页并保存(如baidu、或tomcat的默认页面)
2、添加循环方式去访问
结果证明在socket请求次数达到100后即无法再次访问了(少数次数可以达到一百零几)。
脚本如下:
#include "lrs.h"
int i;
Action()
{
lr_think_time(1);
lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=appsvr01:8080", LrsLastArg);
i=1;
do{
lrs_send("socket0", "buf0", LrsLastArg);
lrs_receive("socket0", "buf1", LrsLastArg);
lr_output_message("-------------lrs request times: %d ", i);
i++;
lrs_send("socket0", "buf2", LrsLastArg);
lrs_receive("socket0", "buf3", LrsLastArg);
lr_output_message("-------------lrs request times: %d ", i);
i++;
lrs_send("socket0", "buf4", LrsLastArg);
lrs_receive("socket0", "buf5", LrsLastArg);
lr_output_message("-------------lrs request times: %d ", i);
i++;
lrs_send("socket0", "buf6", LrsLastArg);
lrs_receive("socket0", "buf7", LrsLastArg);
lr_output_message("-------------lrs request times: %d ", i);
i++;
}while(i<200);
return 0;
}
LoadRunner VUGen日志如下:
...
lrs_send(socket0, buf2)
Action.c(21): lrs_receive(socket0, buf3)
Action.c(22): -------------lrs request times: 98
Action.c(24): lrs_send(socket0, buf4)
Action.c(25): lrs_receive(socket0, buf5)
Action.c(26): -------------lrs request times: 99
Action.c(28): lrs_send(socket0, buf6)
Action.c(29): lrs_receive(socket0, buf7)
Action.c(29): Mismatch (expected 1249 bytes, 1268 bytes actually received)
Action.c(30): -------------lrs request times: 100
Action.c(16): lrs_send(socket0, buf0)
Action.c(17): lrs_receive(socket0, buf1)
Action.c(17): Error : socket0 - Software caused connection abort. Error code : 10053.
Abort was called from an action.
Ending Vuser...
Starting action vuser_end.
vuser_end.c(12): lrs_cleanup()
Ending action vuser_end.
新的发现
在发现以上问题后百思不得其解之后即和一些测试朋友进行讨论交流,但同样没有什么头绪。在一次交流中意外发现朋友的测试脚本中连接的是80端口,于是推断他是用IIS作为测试服务器,突然意识到这是否和应用服务器也有关,立即采用IIS作为服务器进行测试,居然测试通过了,并没有出现Socket连接问题!随后用Weblogic进行测试也同样通过!
初步结论
由以上的各种验证方法发现问题并非单独由LoadRunner引起的,而是和测试的应用服务器也有很大关系。仅当用LoadRunner测试Jboss、Tomcat服务器时才会出现这种问题,而对IIS、Weblogic等问题并不存在。但另有一个奇怪的问题是采用Rational Robot用同样的测试方法,所有的服务器类型都没有问题!
在查找的过程中突然发现了一些关于HTTP的信息,具体如下:
KeepAlive On
在HTTP 1.0中,一次连接只能作传输一次HTTP请求,而KeepAlive参数用于支持HTTP 1.1版本的一次连接、多次传输功能,这样就可以在一次连接中传递多个HTTP请求。虽然只有较新的浏览器才支持这个功能,但还是打开使用这个选项。
MaxKeepAliveRequests 100
MaxKeepAliveRequests为一次连接可以进行的HTTP请求的最大请求次数。将其值设为0将支持在一次连接内进行无限次的传输请求。事实上没有客户程序在一次连接中请求太多的页面,通常达不到这个上限就完成连接了。
KeepAliveTimeout 15
KeepAliveTimeout测试一次连接中的多次请求传输之间的时间,如果服务器 已经完成了一次请求,但一直没有接收到客户程序的下一次请求,在间隔超过了 这个参数设置的值之后,服务器就断开连接。
在对服务器配置文件进行了MaxKeepAliveRequests参数设置后,测试脚本请求次数顺利突破了原有的极限,问题都得到了解决!
---------------------------------------------------------------------------------------------------------------------------------------
测试场景: tomcat 做server, 使用LR 测试上传文件的性能。
LoadRunner总是报错:“Action.c(81): Error -27792: Failed to transmit data to network: [10053] Software caused connection abort”
解决方案:
(1)添加配置 maxKeepAliveRequests=”-1”
Description: The maximum number of HTTP requests which can be pipelined until the connection is closed by the server. Setting this attribute to 1 will disable HTTP/1.0 keep-alive, as well as HTTP/1.1 keep-alive and pipelining. Setting this to -1 will allow an unlimited amount of pipelined or keep-alive HTTP requests. If not specified, this attribute is set to 100.
(2)适当加大 connectionTimeout="60000"
Description: The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. The default value is 60000 (i.e. 60 seconds).
----------------------------------------------------------------------------------------------------------------------------------------------
在今天的测试过程中发现,socket请求连接时总是出错,code是10053,google后把问题已经解决了。关键的点就在于Web服务器(Tomcat/Jboss)的一个参数的配置. "MaxKeepAliveRequests"
MaxKeepAliveRequests为一次连接可以进行的HTTP请求的最大请求次数,其默认值为100。如果将其值设为-1便可支持在一次连接内进行无限次的传输请求。事实上没有客户程序在一次连接中请求太多的页面,通常达不到这个上限就完成连接了。
知道了问题的原因,解决起来就好办了。可以修改或者添加tomcat配置文件server.xml中的连接器(<Connector ... />)的配置。
<Connector port="8090" protocol="HTTP/1.1"
connectionTimeout="20000"
maxKeepAliveRequests="-1"
redirectPort="8443" />
maxKeepAliveRequests="-1"表示: 将支持在一次连接内进行无限次的传输请求
---------------------------------------------------------------------------------------------------------------------------------------------
问题描述:
在用winsocket协议录制脚本后,回放脚本结果报(Software caused connection abort,10053 error)。
现场解决过程:
1、 经查资料,好多地方说这是由于脚本没有关联的原因,于是先对脚本进行参数化及关联,并确保这两项工作设置正确,然后回放脚本,结果脚本还报10053错误。
2、于是开始查HP官方资料及国外网站,结果有人说这是因为应用服务器keppalive参数设置过小,于是开始设置这些参数,结果脚本还报10053错。
3、郁闷至及,便将之先放到一边,三天后某一天突然灵感突发有了一个思想法:目前录制的脚本中打开了好多socket,那么是不是因为打开的多使得数据不能正确传输,于是立刻进行尝试,让脚本运行时每时每刻只有一个socket在打开,当这个socket运行上一会后再将其关闭新开一个新的。很类似将以下内容
{
lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=www.milivio.com.cn:80", LrsLastArg);
lrs_send("socket0", "buf0", LrsLastArg);
lrs_receive("socket0", "buf1", LrsLastArg);
lrs_create_socket("socket1", "TCP", "LocalHost=0", "RemoteHost=www.milivio.com.cn:1433", LrsLastArg);
lrs_send("socket1", "buf2", LrsLastArg);
lrs_receive("socket1", "buf3", LrsLastArg);
lrs_send("socket1", "buf4", LrsLastArg);
lrs_receive("socket1", "buf5", LrsLastArg);
}
修改为
{
lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=www.milivio.com.cn:80", LrsLastArg);
lrs_send("socket0", "buf0", LrsLastArg);
lrs_receive("socket0", "buf1", LrsLastArg);
lrs_send("socket0", "buf2", LrsLastArg);
lrs_receive("socket0", "buf3", LrsLastArg);
lrs_close_socket("socket0");
lrs_create_socket("socket1", "TCP", "LocalHost=0", "RemoteHost=www.milivio.com.cn:1433", LrsLastArg);
lrs_send("socket1", "buf4", LrsLastArg);
lrs_receive("socket1", "buf5", LrsLastArg);
}
这样一做,大功告成!