Android 消息队列之MQTT的使用:物联网通讯,HTTP太重了,使用MQTT;订阅、发送数据和接受数据、会话+消息过期机制,实现双向通讯。

目录

一、前言

  1. HTTP协议在物联网场景的局限性
  2. 切换MQTT的背景原因

二、MQTT协议基础

  1. 协议定义与特点
  2. 核心优势
    • 实时通讯能力
    • 低开销特性
    • 高可靠性保障
    • 连接数优

三、实际应用场景

  1. 室内温湿度数据上传
  2. 设备远程控制
  3. 批量控制实现

四、会话管理、消息过期设置

4.1 会话管理

  1. Clean Session参数
    • 新旧会话模式对比
    • 典型应用场景

4.2 消息过期设置

  1. MQTT 5.0消息过期机制
    • Message Expiry Interval属性
    • QoS级别影响

一、前言

在开发的时候,我们一般都使用Http和后台进行通讯,比如我们是开发物联网的,设备会有很多数据需要频繁发给后台,使用Http来做这件事情,就感觉很重,比如会遇到如下这些问题:

  1. 开发成本:需要后台创建接口,前台去请求。
  2. 连接数过多:在HTTP协议中,每次请求都需要建立一个新的连接,这可能导致连接数过多,特别是在高并发场景下。对于自动售卖机来说,如果同时有大量的用户进行交互,可能会导致服务器资源紧张,影响性能。
  3. 开销较大:HTTP协议的消息头部相对复杂,包含了大量的元数据,这增加了网络传输的开销。
  4. 实时性较差:HTTP协议是基于请求-响应模式的,需要客户端主动发起请求才能获取数据。这导致在实时性要求较高的场景下,HTTP可能无法满足需求。也就是服务器不能主动发数据给客户端。

基于这样的背景,我们选择切换成MQTT


二、是什么

MQTT(Message Queuing Telemetry Transport)是一个轻量级的发布/订阅消息协议,它构建于TCP/IP协议之上,为小型设备提供了稳定的网络通讯。MQTT协议设计简单,易于实现,非常适合在物联网(IoT)和移动应用中使用。

你会发现传递的数据大小是根据你的内容来决定。

能干嘛?

1、实时通讯:MQTT支持异步通讯模式,客户端可以通过订阅主题来接收感兴趣的消息,而不需要主动请求。这使得MQTT非常适合实时通讯和事件驱动的应用场景。

2、低开销:MQTT协议的数据包开销非常小,消息头部仅需2字节,非常适合网络带宽受限或设备资源受限的环境。

3、高可靠性:MQTT支持三种不同的服务质量(QoS)级别,可以根据实际需求选择合适的级别来确保消息的可靠传输。同时,MQTT还具有自动重连机制,能够在网络断开时自动恢复连接。

4、减少连接数:与HTTP相比,MQTT协议只需要客户端与服务器(Broker)建立一次连接就可以进行多次消息发布和订阅,大大减少了网络连接次数和数据传输量。


三、实际应用场景

3.1 室内温湿度数据上传

应该如何设计呢?比如我现在有十台设备,数据都要上传到后台服务器:

  1. 主题:比如你温湿度数据发送到哪个主题,后台服务器这边就会订阅这个主题,
  2. 数据:数据里面需要保护设备的唯一号,这样服务器才知道是哪台设备发上来的。
bash 复制代码
# 设备端:每隔30秒发布数据
client.publish("envmon/D001/sensor", json.dumps(data), qos=1)

# 服务端:订阅所有设备的传感器主题,使用通配符
mosquitto_sub -t "envmon/+/sensor" -v

3.2 后台服务器重启温湿度器

比如有时候,想远程在移动端或web端,关掉温湿度器,那么应该如何设计呢?

  1. 主题:客户端这边订阅指定的主题,一般是以设备唯一号作为主题,后台会往这个主题里面发送消息。这样就能精准的发送到指定的设备上去。
  2. 数据:数据格式,{功能码:开关码}。因为可能会有很多远程功能,所以我们需要设计功能码。
java 复制代码
服务端:
client.publish("envmon/D001/control", xxx, qos=2)

客户端:
client.subscribe("envmon/D001/control", qos=2)

3.2 如果我想实现批量重启呢?或者批量关闭温湿度器呢?

客户端可以订阅多个主题,通过多次调用 subscribe() 方法实现多主题订阅。

scss 复制代码
// 订阅温湿度数据主题
subscribe("envmon/D001/sensor", 1);
subscribe("envmon/D002/sensor", 1);

// 订阅设备控制主题
subscribe("envmon/D001/control", 2);
subscribe("envmon/D002/control", 2);

这里,我们要实现的批量,可以使用通配符

  1. 客户端
java 复制代码
// 订阅所有设备的传感器数据(envmon/任何设备ID/sensor)
subscribe("envmon/+/sensor", 1); 
  1. 服务端:发送所有设备就都能收到。
bash 复制代码
envmon/D001/sensor

如果说,要分组,或者勾选,也可以订阅单条的来进行发送。

四、会话、消息过期设置

4.1 会话

会话,指的是MQTT客户端与MQTT服务端之间的连接。

会话一般可以设置两个参数

  1. 每次打开是否是一个全新的会话,还是延续上一次的会话。
  2. 会话的状态会维持多久。

参数一:是否延续会话(Clean Session)​

​两种模式对比​
场景 Clean Session=true(新会话) Clean Session=false(延续会话)
设备断网后重连 丢失所有订阅和未读消息 自动恢复订阅列表和离线期间消息
适用设备 临时设备(如一次性传感器) 重要设备(如智能门锁)
服务器资源消耗 高(需存储消息)
典型代码场景 setCleanSession(true) setCleanSession(false)

实际案例:​

智能门锁(Clean Session=false):

  1. 门锁断网时,用户通过APP发送开锁指令
  2. 服务器将指令暂存在「会话快递柜」
  3. 门锁网络恢复后,立即收到开锁指令

​参数二:会话有效期(Session Expiry)​

​设置方式​
scss 复制代码
// 设置会话保留时间为1小时(单位:秒)
options.setSessionExpiryInterval(3600); 
​关键行为规则​
有效期设置 服务器行为
0 关闭连接立即销毁会话(等同 Clean Session=true)
3600(1小时) 设备离线后,会话保留1小时,超时后自动清除
0xFFFFFFFF 永久保留会话(慎用!会导致服务器内存泄漏)

也就是,即使Clean Session=false(延续会话),会话有效期设置为60秒,如果离线超过60秒,那么也会清空之前的消息。

4.2 消息过期设置

MQTT 5.0 协议新增了 ​Message Expiry Interval​ 属性,可直接设置消息过期时间。

java 复制代码
import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.eclipse.paho.mqttv5.common.packet.MqttProperties;

// 创建消息并设置过期时间为60秒
MqttMessage message = new MqttMessage();
message.setPayload("Hello".getBytes());
message.setQos(1);

// MQTT 5.0 属性设置
MqttProperties properties = new MqttProperties();
properties.setMessageExpiryInterval(60L); // 单位:秒
message.setProperties(properties);

// 发布消息
client.publish("topic/commands", message);
2. 服务器行为(需支持MQTT5.0)
  • 消息在服务器存储超过设定时间后自动删除
  • 过期消息不会转发给订阅者
  • QoS 2 消息在过期前会完成确认流程
相关推荐
张风捷特烈10 分钟前
每日一题 Flutter#1 | 说说你对声明式 UI 的理解
android·flutter
移动开发者1号1 小时前
Android ContentProvider多表关联查询
android·kotlin
移动开发者1号1 小时前
显式与隐式Intent调用对比
android·kotlin
移动开发者1号1 小时前
Android后台服务保活简介
android·kotlin
移动开发者1号1 小时前
Android后台任务管理利器
android·kotlin
恋猫de小郭2 小时前
Flutter 官方多窗口体验 ,为什么 Flutter 推进那么慢,而 CMP 却支持那么快
android·前端·flutter
yan123687 小时前
Linux 驱动之设备树
android·linux·驱动开发·linux驱动
aningxiaoxixi9 小时前
android stdio 的布局属性
android
CYRUS STUDIO10 小时前
FART 自动化脱壳框架一些 bug 修复记录
android·bug·逆向·fart·脱壳