[TOC]
安装loadrunner_linux代理端
1. loadrunner_linux版下载
下载特别难找,此处是我的百度网盘地址,如果有问题,请联系我:
链接:https://pan.baidu.com/s/1mhDT9AbId5JPQ5lj4WXJug 密码:qfmb
其中 context.zip 为linux版以及c语言写的远程调用lib。
iso镜像为原始的版本,如果不是linux环境使用,其他情况请使用context.zip包。
2.安装
1. 如果可以联网,有yum,可使用yum进行安装
使用root用户,执行如下命令:
- centos 7执行如下命令
yum install compat-libstdc++-33-3.2.3-72.el7.i686 -y
yum install glibc-devel.i686 -y
yum install make -y
yum install gcc -y
yum clean all
- centos6执行如下命令
yum install compat-libstdc++-33.i686 -y
yum install glibc-devel.i686 -y
yum install make -y
yum install gcc -y
- 如果可以联网,但yum源无效,可以进行如下配置:
检查系统版本:
cat /etc/redhat-release
[root@d0d286f085a2 POC001]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
[root@d0d286f085a2 POC001]#
根据不同的版本,把CentOS后面的数字改成对应的数字。(vi CentOS6-Base-163.repo)
# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client. You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the
# remarked out baseurl= line instead.
#
#
[base]
name=CentOS-6 - Base - 163.com
baseurl=http://mirrors.163.com/centos/6/os/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=6&arch=$basearch&repo=os
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
#released updates
[updates]
name=CentOS-6 - Updates - 163.com
baseurl=http://mirrors.163.com/centos/6/updates/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=6&arch=$basearch&repo=updates
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
#additional packages that may be useful
[extras]
name=CentOS-6 - Extras - 163.com
baseurl=http://mirrors.163.com/centos/6/extras/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=6&arch=$basearch&repo=extras
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-6 - Plus - 163.com
baseurl=http://mirrors.163.com/centos/6/centosplus/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=6&arch=$basearch&repo=centosplus
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
#contrib - packages by Centos Users
[contrib]
name=CentOS-6 - Contrib - 163.com
baseurl=http://mirrors.163.com/centos/6/contrib/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=6&arch=$basearch&repo=contrib
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
然后执行
yum makecache
2. 如果没有网,只能内网,则使用安装包中的rpm进行安装
首选将安装包[context.zip]中的文件上传到服务器上的/tmp/下,解压,
- 查看当前linux系统版本,如果是centos7,则执行如下命令
进入context/yum_rpm/c7目录,执行sh ./1.sh
# >> cat 1.sh
# glibc.i686
rpm -ivh libgcc-4.8.5-28.el7_5.1.x86_64.rpm --replacefiles
rpm -ivh glibc-common-2.17-222.el7.x86_64.rpm glibc-2.17-222.el7.x86_64.rpm --replacefiles
rpm -ivh nspr-4.19.0-1.el7_5.x86_64.rpm --replacefiles
rpm -ivh nss-util-3.36.0-1.el7_5.x86_64.rpm --replacefiles
rpm -ivh nss-softokn-freebl-3.36.0-5.el7_5.x86_64.rpm --replacefiles
rpm -ivh libgcc-4.8.5-28.el7_5.1.i686.rpm
rpm -ivh nss-softokn-freebl-3.36.0-5.el7_5.i686.rpm glibc-2.17-222.el7.i686.rpm
rpm -ivh compat-libstdc++-33-3.2.3-72.el7.i686.rpm
# glib-develop
rpm -ivh kernel-headers-3.10.0-862.9.1.el7.x86_64.rpm
rpm -ivh glibc-headers-2.17-222.el7.x86_64.rpm
rpm -ivh glibc-devel-2.17-222.el7.i686.rpm
# make
rpm -ivh make-3.82-23.el7.x86_64.rpm
# gcc
rpm -ivh mpfr-3.1.1-4.el7.x86_64.rpm
rpm -ivh libmpc-1.0.1-3.el7.x86_64.rpm
rpm -ivh cpp-4.8.5-28.el7_5.1.x86_64.rpm
rpm -ivh libgomp-4.8.5-28.el7_5.1.x86_64.rpm
rpm -ivh gcc-4.8.5-28.el7_5.1.x86_64.rpm
再少rpm的话,去阿里的镜像网站查看:https://opsx.alibaba.com/mirror,注意地址,直接mirror.aliyun是没有搜索的。
- 查看当前linux系统版本,如果是centos6,则执行如下命令
进入context/yum_rpm/c6目录,执行sh ./1.sh
# glibc.i686
#rpm -ivh nss-util-3.36.0-1.el7_5.x86_64.rpm --replacefiles
rpm -ivh libgcc-4.4.7-23.el6.x86_64.rpm --replacefiles
rpm -ivh tzdata-2018e-3.el6.noarch.rpm --replacefiles
rpm -ivh glibc-common-2.12-1.212.el6.x86_64.rpm glibc-2.12-1.212.el6.x86_64.rpm --replacefiles
rpm -ivh ppl-0.10.2-11.el6.x86_64.rpm
rpm -ivh cloog-ppl-0.15.7-1.2.el6.x86_64.rpm
rpm -ivh libgcc-4.4.7-23.el6.i686.rpm
rpm -ivh glibc-2.12-1.212.el6.i686.rpm nss-softokn-freebl-3.14.3-23.3.el6_8.i686.rpm
rpm -ivh compat-libstdc++-33-3.2.3-69.el6.i686.rpm
# glib-develop
rpm -ivh kernel-headers-2.6.32-754.2.1.el6.x86_64.rpm --replacefiles
rpm -ivh glibc-headers-2.12-1.212.el6.x86_64.rpm --replacefiles
rpm -ivh glibc-devel-2.12-1.212.el6.i686.rpm --replacefiles
# make
#rpm -ivh make-3.82-23.el7.x86_64.rpm
# gcc
rpm -ivh mpfr-2.4.1-6.el6.x86_64.rpm
rpm -ivh cpp-4.4.7-23.el6.x86_64.rpm
rpm -ivh libgomp-4.4.7-23.el6.x86_64.rpm
rpm -ivh gcc-4.4.7-23.el6.x86_64.rpm
3.安装loadrunner客户端
- 使用root用户,进入 context/Linux下,执行如下命令:
echo -e 'n\na\ni\nf\n'|bash ./installer.sh
- 配置环境变量
如果有root用户或docker,则添加profile
echo -e '\n\nexport PRODUCT_DIR=/opt/HP/HP_LoadGenerator\n
export M_LROOT=$PRODUCT_DIR\n
export LD_LIBRARY_PATH=$M_LROOT/bin:$LD_LIBRARY_PATH\n
export PATH=$M_LROOT/bin:$PATH\n' >> /etc/profile
source /etc/profile
如果非root用户,可以再非root用户添加该环境变量
export PRODUCT_DIR=/opt/HP/HP_LoadGenerator
export M_LROOT=$PRODUCT_DIR
export LD_LIBRARY_PATH=$M_LROOT/bin:$LD_LIBRARY_PATH
export PATH=$M_LROOT/bin:$PATH
4. 启动代理端
source /etc/profile && cd /opt/HP/HP_LoadGenerator/bin/ && ./m_daemon_setup start
查看服务是否启动正常。查看54345端口。(错误日志放在/tmp下面)
ps -ef|grep m_agent_daemon
netstat -anp|grep 54345
- loadrunner客户端配置代理服务
注意勾选`Don't use RSH
配置。
5. 附 Dockerfile
# base image
FROM centos
# MAINTAINER 作者信息
MAINTAINER suitianmou@tfrunning.com.cn
# 拷贝安装镜像
# 赋值context文件夹中的内容到tmp/,并不会复制context本身
COPY context/ /tmp/
## 安装gcc、make等软件包
RUN mkdir /opt/iso \
&& yum install compat-libstdc++-33-3.2.3-72.el7.i686 -y \
&& yum install glibc-devel.i686 -y \
&& yum install make -y \
&& yum clean all \
# centos无此头文件,编译可能会报错
&& touch /usr/include/stropts.h \
# 修改时区
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
# 安装LoadRunner,(next->agree->install->finish)
&& echo -e 'n\na\ni\nf\n'|bash /tmp/Linux/installer.sh \
# 安装tcplib
&& cp /tmp/tcplib/libtcploadcli.so /lib/ \
# 清理安装文件夹
&& rm -rf /tmp/* \
# 修改, 使用ln -s
&& echo -e '\n\nexport PRODUCT_DIR=/opt/HP/HP_LoadGenerator\n\
export M_LROOT=$PRODUCT_DIR\n\
export LD_LIBRARY_PATH=$M_LROOT/bin\n\
export PATH=$M_LROOT/bin:$PATH\n' >> /etc/profile\
&& source /etc/profile \
# 修改root密码
&& echo "pass"|passwd root --stdin \
&& echo -e '#!/bin/bash\nsource /etc/profile && cd /opt/HP/HP_LoadGenerator/bin/ && ./m_daemon_setup start && bash' > /docker_start.sh \
&& chmod 777 /docker_start.sh
# 指定CMD
CMD ["/docker_start.sh"]
构建镜像命令:(需要context放在和Dockerfile同级目录下)
docker build -t loadrunner .
启动容器
docker stop loadrunner
docker rm loadrunner
docker run --name loadrunner -d -p 54345:54345 -it -v /Users/suitm/binsh/docker_lr/:/docker_file loadrunner
3.压测脚本使用
1. 配置远程代理服务器
在Controller
->Run
->Load Generators
中ADD一个新的代理,Name填写地址。平台要选择linux,临时文件目录很重要,后续脚本和日志都在这里面生成。
2. 更新ktcplib的so到linux环境
更新包中context/ktcplib目录,编译会生成libtcploadcli.so
到 /lib
目录。里面包含了基本的tcp通讯,也可以不用这个库,在Aciton.c中写好通讯的程序。
3. 编写CVuser脚本
新建脚本,类型为cvuser类型, 主要是Action.c,下面是一个例子:
#include "lrun.h"
static int HttpHeaderReadln(int sockid, char *buf);
/* 混合消费: AGGREG01 */
#define SENDBUF "{\
\"SYS_HEAD\":{\
\"BRANCH_NO\":\"2204\",\
\"CALL_DATE\":\"20180726\",\
\"CALL_MSGID\":\"{V_USER}{CALL_MSGID}\",\
\"CALL_SYSID\":\"LOADRUNNER\",\
\"CALL_TIME\":\"1708\",\
\"FROM_CHNL\":\"LOADRN\",\
\"SERVICE_CODE\":\"AGGREG01\",\
\"TELLER_NO\":\"0218\"\
},\
\"PAGE\":{\
\"BEG_NUM\":\"0\",\
\"PAGE_NUM\":\"0\"\
},\
\"BODY\":{\
\"BUSI_TYPE\":\"001\",\
\"PAYER_ACNO\":\"{CIF_PAYER}\",\
\"PAYER_AMT\":\"1\",\
\"PAYEE_ACNO\":\"622223199212121\",\
\"PAYEE_AMT\":\"2\",\
\"SCORE\":\"16\",\
\"SCORE_ID\":\"001\"\
}\
}"
//#define HTTP
#define DEBUG
#define CONN_IP "192.168.10.202"
#define CONN_PORT 9922
#define CONTENT_LENGTH "content-length"
#define CONTENT_LENGTH_STEP 2
Action()
{
int ret = 0;
int sock = 0;
char head[200];
char send_buf[2000];
int send_len=0;
char recv_head[200];
char recv_buf[2000];
int recv_len=0;
char res[21];
/* 组报文体 */
memset(send_buf, 0x00, sizeof(send_buf));
strcpy(send_buf, lr_eval_string(SENDBUF));
lr_output_message("send_buf--[%s]", send_buf);
/* 组HTTP报文头 */
#ifdef HTTP
memset(head, 0x00, sizeof(head));
sprintf(head+strlen(head), "POST /message/gateway.do HTTP/1.1\r\n");
sprintf(head+strlen(head), "Content-Language:zh-CN\r\n");
sprintf(head+strlen(head), "Content-Length:%ld\r\n", strlen(send_buf));
sprintf(head+strlen(head), "Host:www.tfrunning.com.cn\r\n");
sprintf(head+strlen(head), "Content-Type:text/xml;charset=utf-8\r\n");
sprintf(head+strlen(head), "Connection:close\r\n");
sprintf(head+strlen(head), "\r\n");
#endif
#ifndef HTTP
sprintf( head, "%04ld", strlen(send_buf));
#endif
ret = lr_load_dll("/lib/libtcploadcli.so");
if (ret != 0)
{
lr_error_message("装载so[%d]", ret);
return -1;
}
/* 连接地址 */
sock = TcpCliOpen(CONN_IP, CONN_PORT);
if (sock < 0)
{
lr_error_message("连接第三方错误[%d]", sock);
return -1;
}
lr_start_transaction("POC压力测试");
/* 发送报文 */
ret = TcpSend(sock, head, strlen(head), 30);
if (ret)
{
lr_end_transaction("POC压力测试", LR_FAIL);
lr_error_message("发送报文失败[%d]", ret);
return 0;
}
ret = TcpSend(sock, send_buf, strlen(send_buf), 30);
if (ret)
{
lr_end_transaction("POC压力测试", LR_FAIL);
lr_error_message("发送报文失败[%d]", ret);
return 0;
}
/* 接收报文 */
#ifdef HTTP
while(1)
{
memset(recv_head, 0x00, sizeof(recv_head));
ret = HttpHeaderReadln(sock, recv_head);
if( ret > 0)
{
lr_output_message("获取到报文头为[%s]", recv_head);
if( strncmp( recv_head, CONTENT_LENGTH, strlen(CONTENT_LENGTH)) == 0 )
{
recv_len = atol(recv_head+strlen(CONTENT_LENGTH)+ CONTENT_LENGTH_STEP);
lr_output_message("获取到报文体长度为[%s][%d]", recv_head, recv_len);
}
}
if( ret == 0)
{
lr_output_message("读取http头结束[%d]", ret);
break;
}
if( ret < 0)
{
lr_end_transaction("POC压力测试", LR_FAIL);
lr_error_message("接收返回包长错误[%d]", ret);
return 0;
}
}
#endif
#ifndef HTTP
ret = TcpRecv(sock, recv_head, 4, 30);
if( ret != 0)
{
lr_end_transaction("POC压力测试", LR_FAIL);
lr_error_message("接收返回包长错误[%d]", ret);
return 0;
}
recv_len = atol(recv_head);
#endif
ret = TcpRecv(sock, recv_buf, recv_len, 30);
if (ret)
{
lr_end_transaction("POC压力测试", LR_FAIL);
lr_error_message("接收返回报文错误[%d],[%d]", ret, recv_len);
return 0;
}
TcpCliClose(sock);
lr_output_message("返回报文[%s]", recv_buf);
memset( res, 0x00, sizeof( res));
if( strstr(recv_buf, "RET_CODE") != NULL)
strncpy( res, strstr(recv_buf,"RET_CODE")+11, 10);
if (0 == strncmp("0000", res, 4))
{
lr_end_transaction("POC压力测试", LR_PASS);
lr_output_message("渠道交易成功!");
}
else
{
lr_end_transaction("POC压力测试", LR_FAIL);
lr_error_message("渠道交易失败,响应码[%s]", res);
}
#ifdef DEBUG
/* 调试用,如果没有error,日志生成结束后会删除 */
lr_error_message("保存运行日志在/tmp/abc/netdir/C/APP/下");
#endif
return 0;
}
static int HttpHeaderReadln(int sockid, char *buf)
{
int ret;
int i = 0;
char tmp[2];
memset(tmp, 0x00, sizeof(tmp));
while (1)
{
if (read(sockid, tmp, 1) <= 0)
return -1;
buf[i] = tmp[0];
if (tmp[0] == '\n' && buf[i - 1] == '\r')
{
i--;
buf[i] = '\0';
break;
}
i++;
}
return i;
}
脚本写法有很多,有以下几点需要注意:
- 加载动态库路径要写对
ret = lr_load_dll("/lib/libtcploadcli.so");
此句话代表要加载的so路径,要和linux环境对应的上。
- 用这种写法之后,不能在windows下调试脚本了,可以写完脚本,然后点击编译。可检查基本错误。
- 参数需要进行配置,才可以生效
lr_eval_string("{CALL_MSGID}"
参数需要在脚本中进行配置,由于是流水号,这里配置的迭代增加。
- lr_output_message会打印日志到linux目录下
具体路径应该是设置的路径/netdir/C/APP/LoadRunner/脚本地址。一个例子如下:
[root@d0d286f085a2 POC001]# pwd
/tmp/abc/brr_sOncLK/netdir/C/APP/LoadRunner/ICESKY/ZYPOC/POC001
[root@d0d286f085a2 POC001]# ls
Action.c POC001.usr mdrvKAUWmx.log mdrvLS8KUU.log mdrvTA46px.log mdrvcUGUZd.log mdrvqJ1cdg.log vuser_end.c
POC001.prm mdrv8778N0.log mdrvKSfX7t.log mdrvRF5UdJ.log mdrvZg3UJK.log mdrvdpVQLz.log mdrvwo6XJK.log vuser_init.c
[root@d0d286f085a2 POC001]#
下面脚本,还有执行生成的日志。 由于不能在windows下调试,所以只能批量执行,可以在调试的时候启动一个用户。
不停的查看该文件夹下日志。
如果没有错误日志,执行结束会清除日志,因此建议在调试的时候,在最后一行加上lr_error_message("调试调试");
常见问题
1. 脚本运行有多个事物
[TOC]
这是loadrunner的bug,解决方法是,点击design->runtime-setting->把最后一项的两个点上,保存,再打开,再取消。