JMeter 压测 MQTT 消息

本文涉及的产品
性能测试 PTS,5000VUM额度
简介: ## 背景信息     MQTT 是专为移动互联网(Mobile Internet)、物联网(IoT)设计的超轻量级消息协议,连接移动端与云服务双向通信,广泛应用于各种应用领域,如端向云汇报状态、云向端推送消息、端向端发送消息(即时聊天)等场景。MQTT 服务性能指标包括支撑同时在线移动端设备数量、消息收发量级、消息延迟等。  &nbs

背景信息

    MQTT 是专为移动互联网(Mobile Internet)、物联网(IoT)设计的超轻量级消息协议,连接移动端与云服务双向通信,广泛应用于各种应用领域,如端向云汇报状态、云向端推送消息、端向端发送消息(即时聊天)等场景。MQTT 服务性能指标包括支撑同时在线移动端设备数量、消息收发量级、消息延迟等。

    可使用 JMeter + MQTT 插件进行 MQTT 压测。

前提条件

  1. 已部署可在公网访问的 MQTT 服务。
  2. 已安装 JMeter 5.x 版本。

安装 MQTT 插件

  1. 下载 mqtt-jmeter 插件最新版本 JAR 包:
    mqtt-xmeter-1.0.1-jar-with-dependencies.jar
  2. 拷贝插件 JAR 包到 JMeter 安装目录的 lib/ext/ 子目录下。
cp mqtt-xmeter-1.0.1-jar-with-dependencies.jar "${JMETER_HOME:?}"/lib/ext/

准备客户端信息 CSV 文件

每个 MQTT 客户端需要提供如下信息:

  • 用户名和密码。

    为保证安全,MQTT 服务器通常需要认证,最常用的认证方式即用户名和密码认证。
    
  • 客户端 ID(ClientId)。

    全局唯一 ID,唯一标识一个客户端,通常与用户设备关联。如关联手机序列号,则可通过客户端 ID 变化检测用户是否更换了新手机。每个用户可能有一个或多个客户端 ID 。
    

    压测前需要预先准备好测试用户和客户端 ID 数据,保存为 CSV 文件供 JMeter 脚本使用。CSV 文件应包含 userNamepasswordclientId 这 3 列数据。如期望压测 10000 台客户端设备同时在线,则需要准备 10000 条客户端信息。

如客户端信息示例 CSV 文件 client.csv 内容如下:

userName,password,clientId
pts_test,pts-pass1,client-test0001
pts_test,pts-pass1,client-test0002
pts_test,pts-pass1,client-test0003

最佳实践:

  • 使用测试用户做性能测试,避免泄露真实用户信息,避免真实用户产生脏数据。
  • 使用预先准备的测试客户端 ID 方便服务器做客户端 ID 校验,同时方便跟踪排查问题。
  • 手工编辑 CSV 文件很容易出错,推荐使用 EXECL、Numbers 等软件导出,或使用 Apache commons-csv
    程序生成。

本地编辑 JMeter 脚本

    本文操作以 JMeter 5.x 英文图形界面为例。打开 选项/Options 菜单,选择 语言/Choose Language > 英语/English 可切换到英文图形界面。

读取客户端 CSV 数据文件。

    打开 JMeter,新建脚本。右键单击 Test Plan ,选择 Add > Threads (Users) > Thread Group 。右键单击 Test Plan ,选择 Add > Listener > View Results Tree ,添加 View Results Tree 监听器,方便本地调试测试脚本。

    JMeter 中一个线程模拟一个 MQTT 客户端设备,使用 Once Only Controller 保证一个线程仅读取一次客户端 CSV 数据文件,绑定一条客户端信息。

  • 右键单击 Thread Group ,选择 Add > Logic Controller > Once Only Controller
  • 右键单击 Once Only Controller , 选择 Add > Config Element > CSV Data Set Config

配置 CSV Data Set Config 如下:

10-csv-config.png

  • Filename 输入客户端信息 CSV 文件名 client.csv
    注意:只输入文件名 client.csv ,不要包含(写死)文件路径,以实现最大的通用性(可移植性),

同时请将 client.csv 文件保存到 JMeter 进程启动目录以保证能够被读取到。

  • File encoding 设置 CSV 文件编码,这里使用 UTF-8
  • Recycle on EOF 选择 False 。一条客户端信息只能被读取使用一次(与一个线程绑定),不允许循环读文件。

建立 MQTT 连接

    同样使用 Once Only Controller 控制一个客户端(对应一个线程)只需执行一次建连操作。右键单击 Once Only Controller,选择 Add > Sampler > MQTT Connect ,配置如下:

20-mqtt-connect.png

MQTT 连接配置:

  • Server name or IP 填写 MQTT 服务器公网地址。客户端设备通常使用公网访问 MQTT 服务。
  • Port number MQTT 服务器端口。填写 1883,即使用标准 TCP 端口。
  • MQTT version 选择 MQTT 版本。选择 3.1.1,目前主流 MQTT 服务器都支持 3.1.1 版本。
  • Timeout(s) 超时秒数填写,即客户端建立连接、发送消息等相关操作的超时时间。填写 10,可按需调整。
  • Protocols 连接协议。选择 TCP,即使用标准 TCP 连接协议。

MQTT 客户端配置:

  • User name 从 CSV 文件读取 userName 字段,填写 ${userName}
  • Password 填写 ${password}
  • ClientId 填写 ${clientId}
  • 取消勾选 Add random suffix for ClientId 。本例使用预先准备好的固定客户端 ID,不要添加后缀。
  • Keep alive(s) 活动心跳间隔秒数。填写 300,连接空闲时,每 5 分钟发送一次活动心跳,可按需调整。

发布消息

右键单击 Thread Group,选择 Add > Sampler > MQTT Pub Sampler ,配置如下:

30-mqtt-pub.png

  • QoS Level 客户端向服务器发布消息的服务质量。选择 0,即只发送一次,丢失不重发,可按需选择其他级别。
  • Topic name 填写消息 topic 。MQTT topic 支持层次结构,使用 / 分割,类似文件路径,如 pts_test/jmeter 等,这里简单使用 pts_test 做测试。
  • 勾选 Add timestamp in payload ,消息头添加发送时间戳,方便测试时检查消息延迟。
  • Payloads 消息体填写 Aliyun PTS From ${clientId},这里在消息体中添加客户端 ID,方便测试和调试检查。

订阅接收消息

右键单击 Thread Group,选择 Add > Sampler > MQTT Sub Sampler ,配置如下:

40-mqtt-pub.png

  • QoS Level 服务器向客户端推送消息的服务质量。选择 0,即只发送一次,丢失不重发,可按需选择其他级别。
  • Topic name 填写消息 topic 。应与发布消息的 topic 匹配,如本例中为 pts_test
  • 勾选 Payload includes timestamp,与发送消息时添加时间戳对应,接收消息后从消息头解析出发送时间,从而计算出消息延迟,即从发布端、途经服务器、最后到达订阅端花费的总时间。
  • Sample on 选择 specified elapsed time (ms),值填写 1000,表示持续接收消息 1000 毫秒。
    这段时间内,可能一条消息都接收不到,也可能接收到多条消息。
  • 勾选 Debug response,记录接收到的消息内容,方便调试排查问题。正式执行性能测试时可取消该选项以优化性能和减少内存占用。

    尝试执行脚本。点击 Thread Group,配置 Loop Count3(循环执行 3 次)。保存并执行脚本,结果如下。

51-result-sub-1.png

52-result-sub-resp.png

添加消息订阅线程组

    当前脚本配置下,执行一次消息订阅可能未收到消息但仍记录为 1 次结果,可能收到多个消息但不能拆分记录消息延迟,导致压测统计数据不准确。为了解决此问题,MQTT Sub Sampler 支持另一种工作模式:每收到一条消息产生一个有效的执行结果,这样将更合理。但这种模式下,没有收到消息时线程将一直阻塞,为了避免阻塞整个线程,应将订阅消息拆分到不同的线程组。

    发布消息线程组移除订阅操作后,应添加等待时间避免单个客户端发布消息过快。实际场景通常是客户端数量多,但每个客户端的消息量少。右键单击 MQTT Pub Sampler ,选择 Add > Time > Constant Timer,设置延时 1000 毫秒,即每次发布消息后等待 1 秒。

55-mqtt-pub-sleep.png

    新建消息订阅线程组,从消息发布线程组复制读取 CSV 和 MQTT 连接配置,共享 CSV 文件。此时一个客户端(对应一条 CSV 记录)要么用于发布消息,要么用于订阅消息,不能两者同时使用。MQTT Sub Sampler 配置 Sample on 选择 number of received messages,值设为 1 ,即每收到一条消息产生一条执行结果。

56-mqtt-sub-msg.png

测试执行脚本结果如下:

57-result-sub-1.png

阿里云 PTS 压测 MQTT 消息

    在 PTS 控制台 新建 JMeter 压测场景 ,上传 mqtt-jmeter 插件 JAR 包、JMeter 脚本和客户端信息 CSV 文件。客户端信息 CSV 文件勾选 切分文件 。高并发压测时,阿里云 PTS 自动根据总并发数分配多台 JMeter 施压机,勾选切分文件保证一条客户端数据只能被一台施压机上的一个线程使用。

60-pts-jmeter-scene.png

在施压配置页,设置并发数和压测时间。

61-pts-jmeter-load.png

注意:

  • 每个线程使用一条客户端信息,总并发数不能大于 CSV 文件提供的客户端信息条数。
  • 脚本包含两个线程组,这里设置的是总并发数,运行时线程组并发数按原脚本设置并发数的比例分配。如原脚本两个线程组并发均为 1,设置场景总并发为 10,则运行时两个线程组并发各为 5 。若原脚本修改发布消息并发数为 2,订阅消息并发数为 1,设置场景总并发为 12,则运行时发布消息并发为 8,订阅消息并发为 4 。

    点击 保存去压测,即可开始压测,压测过程中可看到实时并发数(发布消息客户端和订阅消息客户端总数),TPS 和 RT(消息延迟)等统计信息。

62-pts-jmeter-running.png

    本示例中发布消息为广播,每个消息订阅客户端都收到一份消息,总共有 5 个订阅客户端,因此可看到接收消息数是发布消息数的 5 倍。

    压测结束后将生成压测报告,可查看场景并发、TPS、响应时间等变化趋势图和统计数据汇总等信息。如果出现错误,还可以结合请求采样日志和 JMeter 日志等进行排查。

64-pts-jmeter-report.png

已知问题:

  • 发布消息包含中文字符时,查看接收到的消息包含乱码。这是因为 MQTT 消息体为二进制数据,发布消息时字符串使用系统编码(UTF-8 或 GBK)转为二进制,接收消息时默认使用 ISO-8859-1 将二进制转为字符串,两边编码不一致导致乱码。
相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
1月前
|
测试技术 持续交付 Apache
Python性能测试新风尚:JMeter遇上Locust,性能分析不再难🧐
【10月更文挑战第1天】Python性能测试新风尚:JMeter遇上Locust,性能分析不再难🧐
131 3
|
2月前
|
测试技术 数据库 UED
Python 性能测试进阶之路:JMeter 与 Locust 的强强联合,解锁性能极限
【9月更文挑战第9天】在数字化时代,确保软件系统在高并发场景下的稳定性至关重要。Python 为此提供了丰富的性能测试工具,如 JMeter 和 Locust。JMeter 可模拟复杂请求场景,而 Locust 则能更灵活地模拟真实用户行为。结合两者优势,可全面评估系统性能并优化瓶颈。例如,在电商网站促销期间,通过 JMeter 模拟大量登录请求并用 Locust 模拟用户浏览和购物行为,可有效识别并解决性能问题,从而提升系统稳定性和用户体验。这种组合为性能测试开辟了新道路,助力应对复杂挑战。
108 2
|
3月前
|
测试技术 持续交付 Apache
深度挖掘:Python性能测试中JMeter与Locust的隐藏技能🔍
【8月更文挑战第5天】随着软件规模扩大,性能测试对系统稳定性至关重要。Apache JMeter和Locust是两大主流工具,各有千秋。本文探索它们在Python环境下的进阶用法,挖掘更多性能测试潜力。JMeter功能强大,支持多种协议,可通过命令行模式执行复杂测试计划,并与Python集成实现动态测试数据生成。Locust基于Python,通过编写简洁脚本模拟HTTP请求,支持自定义请求及与Python库深度集成。掌握这些技巧可实现高度定制化测试场景,有效识别性能瓶颈,提升应用稳定性。
128 1
|
3月前
|
缓存 测试技术 Apache
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
【8月更文挑战第5天】性能测试确保应用高负载下稳定运行。Apache JMeter与Locust是两大利器,助力识别解决性能瓶颈。本文介绍这两款工具的应用与优化技巧,并通过实战示例展示性能测试流程。首先,通过JMeter测试静态与动态资源;接着,利用Locust的Python脚本模拟HTTP请求。文中提供安装指南、命令行运行示例与性能优化建议,帮助读者掌握性能测试核心技能。
129 0
|
15天前
|
测试技术 持续交付 Apache
Python性能测试新风尚:JMeter遇上Locust,性能分析不再难🧐
Python性能测试新风尚:JMeter遇上Locust,性能分析不再难🧐
41 3
|
13天前
|
缓存 测试技术 Apache
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
30 1
|
2月前
|
缓存 Java 测试技术
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
使用JMeter对项目各个接口进行压力测试,并对前端进行动静分离优化,优化三级分类查询接口的性能
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
|
1月前
|
缓存 测试技术 Apache
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
【10月更文挑战第1天】告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
61 4
|
2月前
|
测试技术 持续交付 Apache
Python性能测试新风尚:JMeter遇上Locust,性能分析不再难🧐
【9月更文挑战第10天】随着软件应用的不断扩展,性能测试成为确保系统稳定运行的关键环节。本文通过对比Apache JMeter和Locust,探讨了如何在Python环境中利用这两款工具挖掘更多性能测试潜力。JMeter是一款成熟且功能强大的开源工具,支持多种协议,适用于各种应用的测试;而Locust则基于Python,通过简单脚本模拟HTTP请求,更适合Web应用测试。
93 3
|
2月前
|
缓存 测试技术 Apache
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
【9月更文挑战第5天】性能测试是确保应用在高负载下稳定运行的关键。本文介绍Apache JMeter和Locust两款常用性能测试工具,帮助识别并解决性能瓶颈。JMeter适用于测试静态和动态资源,而Locust则通过Python脚本模拟HTTP请求。文章详细讲解了安装、配置及使用方法,并提供了实战案例,帮助你掌握性能测试技巧,提升应用性能。通过分析测试结果、模拟并发、检查资源使用情况及代码优化,确保应用在高并发环境下表现优异。
76 5