phd 2018-11-04
背景:由于第一次接触zeromq,对其了解甚少,于是度娘对其原理了解一番后,就开始了接下来实践“坑”中,首先在LR中,对于用socekt、java、c那种方式来实现,通过抓包对比,以及socekt和c语言可实现,但复杂度有点”呵呵“,而用java开发的zeromq请求脚本(见:实现过程一),实现挺简单,但是在回放脚本时,遇见了我一个”大坑“,由于开发的隐瞒,导致回放的结果总是乱码,后面通过加编码方式,始终不行,于是判断是否开发加了其他加密方式,结果如我所料,开发对返回数据采用了protobuf反序列,于是只能傻眼、蒙逼,乖乖的百度了解protobuf原理,发现大多都是转换成c++、python、java等代码来解析数据,庆幸的是,开发将python实现了解析数据方法发给我,可悲剧的是,loadrunner不支持python语言开发,于是只能决定用java来实现zeromq接收数据和数据反序列(见:实现过程二),但开发过程中,遇见的第二个”大坑“,发现proto文件生成java代码中,存在类与类之间依赖关系问题无法解决情况,此方法也只能作罢。再次选择调整思路,想到开发已经写好的python代码,能否直接调用python代码,通过百度,这种思路是可以的,但有2种方式,第一种采用jpython来调用,第二种采用cmd调用,通过操作,遇到了第三个“大坑”,发现jpython方式,很容易出现python文件中import包,无法引用python底层包,也需第一次用jpython,了解不深吧,最终也只能选择暂时放弃,最后选择采用cmd调用,却能成功调用到,但存在一些注意事项(见:实现过程三)。
实现过程一:
1、loadrunner引用的zmq.jar包,要jdk1.6的32位生成,否则引用进来会报错,原因:loadrunner11只支持32位的jdk1.6,
参考下载地址:https://download.csdn.net/download/liu_xp2003/8981985 或
https://blog.csdn.net/sinat_29673403/article/details/53195733
2、将以上下载的压缩包里,找到jzmq.dll和 libzmq.dll 文件,并把这两个问题,放到jdk1.6的安装路径下in目录下
3、LR编写java vuser代码:
import java.io.IOException;
import java.net.URLDecoder;
import java.util.StringTokenizer;import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Socket;
import lrapi.lr;
public class Actions
{
ZMQ.Socket subscriber;
ZMQ.Context context;
public int init() throws Throwable {
context = ZMQ.context(1);
System.out.println("Connecting to hello world server...");
subscriber = context.socket(ZMQ.SUB);
subscriber.connect("tcp://ip:端口");
String request = "";
lr.log_message("Send data: "+request);
subscriber.subscribe("".getBytes());
while(true){
byte[] stringValue = subscriber.recv(0);
String message =new String(stringValue);
lr.log_message("recv data01:"+message);
lr.think_time(1);
}
}//end of init
public int action() throws Throwable {
return 0;
}//end of action
public int end() throws Throwable {
subscriber.close();
context.term();
return 0;
}//end of end
}
结果:无法实现zeromq返回数据protobuf反序列化
实现过程二:
对照开发python代码思路,用参考开发protobuf版本下载(参考地址:https://blog.csdn.net/junerseven7/article/details/71077875?utm_source=blogxgwz2), 将proto文件,生成java代码
建立项目,引用zmq相关包,以及protoc生成的java代码,发现这些新生成的java代码,存在很多问题(1、依赖关系存在问题;2、生成的单个java文件有些超过10几w行,总是开发工具崩溃,后续也尝试了,根据文件大小,进行生成java文件,但是文件之间依赖关系问题)
结果:无法实现zeromq返回数据protobuf反序列化
实现过程三:
先安装python,并配置环境变量(如果不配置环境变量,java vuser代码中,就需要python.exe的绝对路径)
用pip安装zmq包
安装32位的jdk1.6,并配置环境变量
将将protobuf生成的python代码文件(需下载protoc来生成),放到proto文件夹中
在loadrunner中新建java vuser后,将proto文件夹和调用zmq发送和接收数据的xxx.py文件,放到脚本路径下。(如果protobuf生成的python代码文件和xxx.py文件不放在lr脚本目录,请修改java vuser代码中路径,以及xxx.py文件中sys.path.append('./proto')的proto路径位置)
xxx.py代码:
#!/usr/bin/env python
# -*- coding=utf-8 -*-
import sys
sys.path.append('./proto')
import zmq
# 导入protobuf文件
import messages_pb2
ip = "xxx.xxx.xxx.xxx"
port = 'xxxx'
if len(sys.argv) == 3:
print("请输入Ip和Port")
ip = sys.argv[1]
port = sys.argv[2]
print("ip = %s port = %s" % (ip, port))
class SubData():
def __init__(self):
self.ctx = zmq.Context()
self.subSock = self.ctx.socket(zmq.SUB)
self.subSock.connect("tcp://%s:%s" % (ip, port))
self.subSock.setsockopt(zmq.SUBSCRIBE, "")
def Sub(self):
while (True):
qdata = messages_pb2.Qdata()
qdata = messages_pb2.Data()
recvData = self.subSock.recv_multipart()
print(len(recvData))
if len(recvData) == 2:
data.ParseFromString(recvData[1])
qdata .ParseFromString(data.Message)
print(qdata)
if __name__ == '__main__':
sub_data = SubData()
sub_data.Sub()
5、java vuser代码,主要实现cmd调用xxx.py文件,通过xxx.py文件,执行zmq数据接收,以及protobuf反序列:
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import lrapi.lr;
public class Actions
{
public int init() throws Throwable {
return 0;
}
public int action() throws Throwable {
try {
System.out.println("start");
Process pr = Runtime.getRuntime().exec("python ./xxx.py");
BufferedReader in= new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
pr.waitFor();
System.out.println("end");
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}//end of action
public int end() throws Throwable {
return 0;
}//end of end
}
结果:可成功采用cmd方式调用python文件,并执行zeromq请求和数据protobuf反序列化
总结:
1、为了短期完成lr脚本开发,采用cmd执行python的方式,只能说暂时一个解决方式,不是最佳解决方式,还需继续摸索java直接实现zeromq请求和数据protobuf反序列化,这种最佳方式,研究为什么protoc生成java代码会出现类依赖问题。
2、接触一种新事物时,一定要了解其原理,不能一味去堆代码,导致返工。