基于LoadRunner的UDP和TCP服务性能测试

发表于:2019-8-16 10:11

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:AstrophelYang    来源:网络

  背景
  最近项目要做性能测试,要出要一份性能报告,让我出一个有关Tcp和Udp的功能模块的测试,流程大概是这样,先走TCP协议协商一下会话,协商成功后走Udp收发数据。
  有点简单啊,自己写个功能模块测一下,然后把结果展示出来就ok了。
  然而想法很美好,现实有点残酷。idea瞬间被pass掉,理由就是自己写的测试模块木有说服力。
  要用专业的测试工具来搞,才有说服力。作为一名开发,用测试工具是不可能的,就算饿死也不会用!!!
  最后还是学了一下LoadRunner,在历经一番坎坷摸索之后,出了个测试脚本。不得不说,LR真的挺好用的。(PS:真香现场)
  不说废话了,在网上找了一下使用LR测试TCP和UDP的脚本,资料有点难找,大多都是简单概况一下。(让我一个LR初手,搞不定啊),最后在自己一番摸索之下,把过程整理一下,要有啥不好的地方,还请多指教一下。
  准备工作
  LoadRunner 环境,这个大家自行百度,教程太多我就不详说了
  数据包,客户端进行TCP协商的数据包,使用udp发送的数据包(用wireshark抓取)
  LR的测试脚本
  编写测试脚本
  使用LR测试TCP和UDP要使用LR中Windows sockets协议,它可以模拟tcp/ip协议和服务器进行数据交互,这样便可以模拟终端来进行性能测试了。首先打开LR Virtual User Generator选择创建脚本。
  图:创建脚本
  选择创建windows sockets协议的脚本。
  图:选择socket协议
  接着会出来一个录制选项框,在应用类型里有两种选择,一种是win32的应用,一种是浏网络应用,选择后可以开始录制脚本,会启用对应的应用,根据操作录制脚本。
  图:初始化参数
  我这边使用网络应用,输入要测试服务的URL,选择对应的action,然后点击ok就可以开始录制。
  这里可以选择的活动对应有三种
  vuser_init:创建虚拟用户初始化时做的事情, 比如要测试业务某个具体业务操作环节时,可以先把系统用户登录的写在init中。
  action:       用户操作的事件,即需要测试业务操作点。
  vuser_end:虚拟用户退出的时候做到操作,如关闭socket等。
  不过录制脚本这个功能生成的测试脚本有的时候不符合我们的预期,还是要自己修改,所以我这里随便录制了一下,然后重写脚本。
  图:结束录制
  点击结束录制,会生成脚本,如下图,然后我们就可以自己修改脚本了。
  最后就是最关键的地方了,根据具体业务流程来编写测试脚本,我这里总体业务流程大致如下
  编写vuser_init
  我这里由于要协商会话,所以在初始化时需要发送两次请求和接受两次请求,脚本如下
   vuser_init()
  {
  char*recvbuf;
  int recvlen=0;
  int rc=0;
  lrs_startup(257);
  //设定开始事务
  lr_start_transaction("Trans_Session");
  lr_start_transaction("Conn_TCP");
  //创建socket
  rc=lrs_create_socket("socket0","TCP","LocalHost=0","RemoteHost=127.0.0.1:8888",LrsLastArg);
  //判断套接字创建是否成功
  if(rc!=0){
  lr_end_transaction("Conn_TCP",LR_FAIL);
  lr_end_transaction("Trans_Session",LR_FAIL);
  return 0;
  }
  lr_end_transaction("Conn_TCP",LR_PASS);  //判断socket是否链接成功的事务,0表示创建成功
  lrs_send("socket0","senCreateReqBuf",LrsLastArg); //发送安全会话建立请求,senCreateReq为在data.ws中定义的发送变量
  lrs_receive("socket0","senCreateRspBuf",LrsLastArg); //接收消息,存放在senCreateReq中,senCreateReq是在data.ws中定义的接收数组,注意数组长度一定要大于等于实际接收长度
  lrs_get_last_received_buffer("socket0",&recvbuf,&recvlen);//把Socket最后接收的字节数组,长度放在recvlen中,内容放在recvbuf中
  if(recvlen<100) {
  lr_end_transaction("Trans_Session",LR_FAIL);
  }
  lrs_send("socket0","authReqBuf",LrsLastArg); //发送authRsp,authRsp为在data.ws中定义的发送变量
  lrs_receive("socket0","authRspBuf",LrsLastArg); //接收消息,存放在authRep中,authRep是在data.ws中定义的接收数组,注意数组长度一定要大于等于实际接收长度
  lrs_get_last_received_buffer("socket0",&recvbuf,&recvlen);//把Socket最后接收的字节数组,长度放在recvlen中,内容放在recvbuf中
  if(recvlen>60)
  lr_end_transaction("Trans_Session",LR_PASS);
  else
  lr_end_transaction("Trans_Session",LR_FAIL);
  return 0;
  }
  1. 首选创建相关测试的事务,在性能测试中这个可以作为测试用例通过的依据lr_start_transaction与lr_end_transaction 为使用最多的事物创造组合函数,lr_start_transaction为事物开始函数,lr_end_transaction为事物结束函数,并负责记录事物的运行时间.
  语法格式如下:
  int lr_start_transaction (const char * transaction_name);
  int lr_end_transaction (const char * transaction_name,int status);
  其中transacton为事物名称,status为事物的结束状态,共有LR_PASS(通过)、LR_FAIL(失败)、LR_AUTO(自动)、 LR_STOP(暂停),其中LR_PASS默认的是LR_PASS,可以在事物结束前通过lr_set_transaction_status进行修改。如果在lr_end_transaction中没有指定结束事物状态是LR_AUTO,而是明确制定为LR_PASS、LR_FAIL、 LR_STOP其中的其中,则事物将以最后制定状态来结束。需要注意,事物开始没有lr_end_transaction没有结束的时候,不能用相同的事 物名称,除非这个事物已经通过lr_end_transaction结束。
  2. 接着创建socket,初始化套接字,使用的函数如下
  int lrs_create_socket("socket0","TCP","LocalHost=0","RemoteHost=127.0.0.1:8888",LrsLastArg);
  参数分别是:socket名称、协议类型(TCP或UDP)、链接类型(远程链接:RemoteHost、本地:LocalHost、或者本地监听)、LrsLastArg 参数结束标记,创建成功返回0。
  3. 创建完套接字后,判断时候成功,若是失败将对应的事务状态修改为LR_FAIL。
  4.通过socket发送数据,lrs_send("socket0","senCreateReqBuf",LrsLastArg); 这里senCreateReqBuf为待发送的数据,数据存在data.ws文件中。
  send 后面填的是待发送数据buf的名称,接着再跟上待发送数据的长度 ,待发送buf在LR中我这边是以16进制发送,按照LR的规则需要在16进制值前中加上\x,很明显构造这个数据还是麻烦的很。所以这里提供一个比较方便的方式。
  我们可以从wireshark中直接抓取对应格式的数据,选择需要的数据,右键复制,选择转义字符串,就可以了,最后将复制的数据放在data.ws中就可以了。
  5.接收响应数据,判断响应数据是否正确,我这里根据长度来判断。
  编写Action
  在Action文件中编写需要测试的操作步骤,我这里就是发送udp请求,接受响应,判断响应是否正确,代码如下
   Action()
  {
  char*recvbuf;
  int recvlen=0;
  int rc=0;
  lr_start_transaction("Trans_UDP");
  lr_start_transaction("Conn_UDP");
  rc=lrs_create_socket("socket1","UDP","RemoteHost=127.0.0.1:8887",LrsLastArg);
  if (rc != 0) {
  lr_end_transaction("Conn_UDP",LR_FAIL);
  lr_end_transaction("Trans_UDP",LR_FAIL);
  return 0;
  }
  lr_output_message("Received:%d",rc);
  lr_end_transaction("Conn_UDP",LR_PASS);
  lrs_send("socket1","ReqBuf",LrsLastArg); //发送ReqBuf,ReqBuf为在data.ws中定义的发送变量
  lrs_receive("socket1","RspBuf",LrsLastArg); //接收消息,存放在RspBuf中,RspBuf是在data.ws中定义的接收数组,注意数组长度一定要大于等于实际接收长度
  lrs_get_last_received_buffer("socket1",&recvbuf,&recvlen);//把Socket最后接收的字节数组,长度放在recvlen中,内容放在recvbuf中
  if(recvlen>=128) {
  lr_end_transaction("Trans_UDP",LR_PASS);
  } else {
  lr_log_message("Error UDP Received length:%d",recvlen);
  lr_end_transaction("Trans_UDP",LR_FAIL);
  }
  //--------------断开socket--------------
  lrs_disable_socket("socket1",DISABLE_SEND_RECV);
  //--------------关闭socket--------------
  lrs_close_socket("socket1");
  return 0;
  }
   原理和上文提的基本一致,这里就不再多说了
  编写vuser_init
  编写结束时的操作,这里就是关闭init中的socket
   vuser_end()
  {
  //--------------断开socket--------------
  lrs_disable_socket("socket0", DISABLE_SEND_RECV);
  //--------------关闭socket--------------
  lrs_close_socket("socket0");
  return 0;
  }
  运行测试脚本
  点击start,执行脚本,运行无误,说明脚本正确
  至此测试脚本编写完毕,可以正式开始性能测试了
  性能测试
  始运行LR执行性能测试
  这里我们将刚刚编写好的的测试脚本添加进去
  然后配置相关的测试参数,如并发数,测试时间等,开始测试
  观察测试结果
  最后在运行结束后,我们可以根据分析报告诊断性能测试结果,还可以配合jvisualvm工具诊断热点方法,提升程序性能
  总结
  我们可以LR可以配合jvisualvm工具诊断热点方法,提升程序性能。如果有大神看出什么端倪的话,欢迎批评斧正,个人感觉还有提升空间

     上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号