self.topic = topic
self.payload = payload
self.start_time = start_time
self.timeout = timeout
统计总共发送成功的消息数量
total_published = 0
disconnect_record_list = [] # 定义存放连接断开的记录的列表容器
class PublishTask(TaskSet):
@task
def task_publish(self):
self.client.loop_start()
topic = TEST_TOPIC
payload = BYTES_DATA
记录发送的开始时间
start_time = time.time()
mqtt_msg_info = self.client.publish(topic, payload, qos=1, retain=False)
published_mid = mqtt_msg_info.mid
将发送成功的消息内容,放入client实例的 published_message 字段
self.client.published_message[published_mid] = MQTTMessage(REQUEST_TYPE,
0,
topic,
payload,
start_time,
PUBLISH_TIMEOUT)
发送成功回调
self.client.on_publish = self.on_publish
断开连接回调
self.client.on_disconnect = self.on_disconnect
@staticmethod
def on_disconnect(client, userdata, rc):
“”" broker连接断开,放入列表容器"“”
disconnected_info = [str(client._client_id), rc, datetime.datetime.now()]
disconnect_record_list.append(disconnected_info)
print(“rc状态:{} - -”.format(rc), “{}-broker连接已断开”.format(str(client._client_id)))
@staticmethod
def on_publish(client, userdata, mid):
if mid:
记录消息发送成功的时间
end_time = time.time()
从已发送的消息容器中,取出消息
message = client.published_message.pop(mid, None)
计算开始发送到发送成功的耗时
publish_resp_time = calculate_resp_time(message.start_time, end_time)
fire_success(
request_type=“p_success”,
name="client_id: " + str(client._client_id),
response_time=publish_resp_time,
response_length=len(message.payload),
exception=None,
context=None
)
global total_published
成功发送累加1
total_published += 1
class MQTTLocustUser(User):
tasks = [PublishTask]
wait_time = between(2, 2)
def init(self, *args, **kwargs):
super().init(*args, **kwargs)
从队列中获取客户端 username 和 client_id
current_client = client_queue.get()
self.client = mqtt_client.Client(current_client[1])
self.client.username_pw_set(current_client[0], PASSWORD)
self.client.username_pw_set(current_client[0] + “1”, PASSWORD) # 模拟client连接报错
定义一个容器,存放已发送的消息
self.client.published_message = {}
def on_start(self):
设置tls
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
self.client.tls_set_context(context)
self.client.connect(host=BROKER_ADDRESS, port=PORT, keepalive=60)
self.client.on_connect = self.on_connect
def on_stop(self):
print(“publish 成功, 当前已成功发送数量:{}”.format(total_published))
if len(disconnect_record_list) == 0:
print(“无断开连接的client”)
else:
把断开记录里的信息写入csv
with open(“disconnect_record.csv”, “w”, newline=‘’, encoding=‘UTF8’) as csvfile:
writer = csv.writer(csvfile)
writer.writerow([‘client_id’, ‘rc_status’, ‘disconnected_time’])
for i in disconnect_record_list:
writer.writerow(i)
print(“断开连接的client信息已写入csv文件”)
@staticmethod
def on_connect(client, userdata, flags, rc, props=None):
if rc == 0:
print(“rc状态:{} - -”.format(rc), “{}-连接broker成功”.format(str(client._client_id)))
fire_success(
request_type=“c_success”,
name=‘count_connected’,
response_time=0,
response_length=0,
exception=None,
context=None
)
else:
print(“rc状态:{} - -”.format(rc), “{}-连接broker失败”.format(str(client._client_id)))
fire_success(
request_type=“c_fail”,
name="client_id: " + str(client._client_id),
response_time=0,
response_length=0,
exception=None,
context=None
)
if name == ‘main’:
run_single_user(MQTTLocustUser)
- 代码分析-locust库部分
并发请求能力还是使用的locust
库的能力。官方只提供了http
协议接口的相关类,没直接提供mqtt
协议的,但是我们可以按照官方的规范,自定义相关的类,只要继承User
和TaskSet
即可。
User类
首先是先定义User
类,这里就是用来生成我要用来测试的车辆。
类初始化的时候,黄色框里,会去队列里取出车辆信息,用来做一些相关的设置。client
来源于from paho.mqtt import client as mqtt_client
提供的能力,固定用法,按照人家的文档使用就行。
红色框里,是User
类的2个重要熟悉属性:
tasks
: 这里定义了生成的用户需要去干哪些事情,也就是对应脚本里的PublishTask
类下面定义的内容。wait_time
: 用户在执行task时间隔停留的时间,可以是个区间,在里面随机。我这里意思是每2s发送一次数据到broker。
绿色框里,定义了一个字典容器,用来存放当前用户已发送成功的消息内容,因为后面我要取出来把里面相关的数据写到生成的报表中去。
蓝色框里有2个方法,也是locust
提供的能力:
on_start
:当用户开始运行时调用,这里我做了车辆连接broker代理的处理,注意这里需要设置tls,因为服务连接需要。
on_stop
:当用户结束运行时调用,这里我做了一些其他的处理,比如把运行期间断开连接的车辆信息写到本地csv中。
TaskSet类
定义好User
类,就需要来定义TaskSet
类,你得告诉产生出来的用户,要干点啥。
我这根据业务需要,就是让车辆不停的像broker发送数据即可。
红色部分,同样是paho.mqtt
提供的能力,会启动新的线程去执行你定义的事情。
黄色部分,就是做发送数据的操作,并且我可以拿到一些返回,查看源码就可以知道返回的是MQTTMessageInfo
类。
注意返回的2个属性:
mid
: 返回这个消息发送的顺序rc
: 表示发送的响应状态,0 就是成功
绿色部分,还记得我在上面的User
类中定义了一个容器,在这里就把发送的消息相关信息放到容器中去,留着后面使用。
- 代码分析-paho.mqtt库部分
上面的代码已经用到了不少paho.mqtt
的能力,这里再进行整体梳理下。
- client.Client():声明一个client
- client.username_pw_set(): 设置客户端的用户名,密码
- client.tls_set_context: 设置ssl模式
- client.connect(): 连接代理
- client.publish:向代理推送消息
还用到了一些回调函数:
- on_connect:连接操作成功时回调
- on_publish:发布成功时回调
- on_disconnect:客户端与代理断开连接时回调
另外还用到了一个事件函数events.request
。
当客户端发送请求时会调用,不管是请求成功还是请求失败;当我需要自定义我的报告内容时,就需要用到这个event
。
查看源码,知道里面要传哪些参数,那我们在调用时候就需要传入对应的参数。
比如我在发送回调函数里调用了该方法。
所以最后在控制台显示的报告里就有我定义的内容了。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数软件测试工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上软件测试开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注软件测试)
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-Byv2bkyD-1713022066178)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!