前端mqtt使用调研

本文深入讲解MQTT协议,一种轻量级的发布/订阅模式通讯协议,特别适用于物联网场景。探讨了MQTT的原理,包括客户端和服务端角色,以及如何在前端实现长链接通信。此外,还介绍了如何在React项目中使用mqttws31.js库实现MQTT连接,并提供了代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,是 TCP/IP 的再封装,由 IBM 在 1999 年发布。MQTT 最大优点在于,地开销,少流量实现网络通信

协议原理

mqtt 协议中有两种角色,客户端和服务端。服务端一般由消息 broker 实现,MQTT 与传统 HTTP 协议有所不同,所有接入的设备都为客户端。

客户端有两种身份发布者(Publish)、订阅者(Subscribe),也可以同时具备两者身份。

顾名思义,发布者可以发布消息,订阅者可以接受消息。

消息内容

MQTT 传输的消息分为:主题(Topic)和负载(payload)两部分:

  • (1)Topic,主题,订阅者订阅指定主题后,会收到其他发布者发送到该主题的数据;
  • (2)payload,具体的载荷

关键字

一、订阅(Subscription)

订阅包含主题筛选器(Topic Filter)和最大服务质量(QoS)。订阅会与一个会话(Session)关联。一个会话可以包含多个订阅。每一个会话中的每个订阅都有一个不同的主题筛选器。

二、会话(Session)

每个客户端与服务器建立连接后就是一个会话,客户端和服务器之间有状态交互。会话存在于一个网络之间,也可能在客户端和服务器之间跨越多个连续的网络连接。

三、主题名(Topic Name)

连接到一个应用程序消息的标签,该标签与服务器的订阅相匹配。服务器会将消息发送给订阅所匹配标签的每个客户端。

四、主题筛选器(Topic Filter)

一个对主题名通配符筛选器,在订阅表达式中使用,表示订阅所匹配到的多个主题。

五、负载(Payload)

具体数据

前端实现

前端一般使用 websocket 协议实现长链接通信,为了简化 websocket 协议编程,可以直接使用建立在 websocket 上的 mqtt 协议,能够直接得到登陆鉴权、消息分发的功能,免去手动编程解析。

前端 websocket 的 mqtt 协议依赖 mqttws31.js 库实现。

react 项目中,在public/index.html中引入

<script type="text/javascript" src="./static/mqttws31.js"></script>

组件中调用:

this.mqttClient = new Paho.MQTT.Client(hostname, port, clientId);
this.mqttoptions = {
			invocationContext: {
				host: hostname,
				port: port,
				clientId: clientId
			},
			timeout: 5,
			cleanSession: false,
			useSSL: false,
			userName: 'chrome',
			password: 'chrome',
			onSuccess: this.mqttConnectOk,
			onFailure: this.mqttConnectFail
		};
mqttConnectOk = () => {
		console.log('WebSocket mqtt 连接成功!');
		console.log('开始订阅主题');
		this.mqttClient.subscribe('out');
		console.log('订阅完成');
	};
mqttConnectFail = e => {
		console.log('MQTT连接失败,失败原因是', e);
	};

messageArrived = message => {
			let data =`MQTT 收到topic 为 ${message.destinationName} 的消息,具体内容为: ${message.payloadString}, 消息服务等级为 ${message.qos}:`
	console.log(data);
};
connectLost = response => {
	console.log('MQTT 连接断开');


};
componentDidMount() {

		this.mqttClient.onMessageArrived = this.messageArrived;
		this.mqttClient.onConnectionLost = this.connectLost;
		console.log('开始进行mqtt链接');
		this.mqttClient.connect(this.mqttoptions);
	}

主要 API

引入依赖文件后,能够得到一个全局的Paho.MQTT对象,主要 API 是该对象下的方法,包括主动连接、断开、发送数据以及收到数据的回掉函数接口

1.生成 mqtt 客户端

this.mqttClient = new Paho.MQTT.Client(hostname, port, clientId);

2.建立连接

this.mqttClient.connect(option);

option 为配置参数,包括以下内容

invocationContext: {
	host: hostname,//地址
	port: port,//端口
	clientId: clientId//链接id
},
timeout: 5,//链接超时时间
cleanSession: false,//是否清楚session
useSSL: false,//是否使用ssl加密
userName: 'chrome',/用户名
password: 'chrome',//密码
onSuccess: this.mqttConnectOk,//连接成功回调函数
onFailure: this.mqttConnectFail//连接失败回调函数

3.订阅主题

this.mqttClient.subscribe("topic name");

Topic name 为订阅的主题

4.接收数据

this.mqttClient.onMessageArrived = this.messageArrived;

接受数据通过回调函数进行处理,回调函数参数是信息体,包括收到的主题名称,数据,Qos 等数据

5.发送数据

message = new Paho.MQTT.Message("Hello");
message.destinationName = "/World";
client.send(message);

destinationName 为发送的主题名称

message 为要发送的数据

6.连接断开

this.mqttClient.onConnectionLost = this.connectLost;

连接断开也是通过回调函数来处理,入参数是失败的原因。在这里可以进行重连,如下。

connectLost = (response) => {
  console.log("MQTT 连接断开");
  console.log("MQTT 开始重连");
  this.mqttoptions = Object.assign({}, this.mqttoptionsback); //mqttoptionsback 为 链接option初始化时拷贝的值。
  this.mqttClient.connect(this.mqttoptions);
  console.log("MQTT 重连完成");
};

注意:重连时使用的链接 option 对象不能直接使用上一次链接成功后的 option 因为该对象已经被修改。

问题调研

1. 能否控制页面不刷新(消息防丢失处理)

控制页面不刷新的目的是防止实时消息的丢失,在用此用户实际浏览网页过程中,刷新只是一个短暂而又快速的过程,而前端进行 mqtt 连接时将连接配置项clean设置为 false,Qos 设置为 1 或者 2,能够实现即时恰巧用户在刷新网页是 后台通过 mqtt 推送了消息,错过了此次推送,待到刷新完毕 mqtt 进行再次连接时仍然能够接收到刚才错过的消息。

该配置项含义如下:

  1. clean:false,上文提到,无论是 tcp 实现的 mqtt 还是 websocket 实现的 mqtt,只要客户端与 broker 建立连接后 broker 就维护了一个 session 会话,包含了这个链接的所有信息,消息的收发也是通过该 session 实现的,session 的 key 时客户端链接时的 clientId。当 clean 设置为 false 时,意味着通知 broker,当该客户端掉线后不要清除客户端消息,下次重联客户端仍然采用与之前相同的 clientId 进行链接。
  2. Qos 为消息服务质量,当设置为 1 或者 2 时,服务端向客户端订阅的某一个主题推送数据时,客户端处在刷新掉线情况下,没有对服务端进行回复,服务端会存储消息到 senssion 中,待到客户端恢复链接后,重新推送给订阅此主题的客户端。(这里客户端的恢复是有 mqtt 协议底层实现的,一般在库中已经实现,使用时不用关心)

消息服务质量 Qos 分别如下:

  1. QoS0,最多一次送达。
  2. QoS1,至少一次送达。
  3. QoS2,准确一次送达。

2. 消息去重

当设置为 qos1 或者 qos2 时可能会出现收到重复消息,此时可以在消息数据中增加应用序号,每次收到后对比,如果重复则丢弃

业务需求实现调研

引入 mqtt 主要是为了满足实时消息推送和在线聊天需求。这两个需求实现需要后台程序、mqtt broker、前台程序相互配合,在技术上可简化为业务服务器实现 数据下发接受数据上报两个功能,这里的业务服务器指框图中的后台程序。

在这里插入图片描述

下面分功能介绍具体实现

消息推送

用户在登录系统时,根据返回的用户名密码以及 mqtt 地址,与 mqttBroker 进行连接,连接成功后订阅以下主题:

  1. broadcast/company/公司id/role/角色id/user/用户id
  2. broadcast/company/+
  3. broadcast/company/公司id/role/+
  4. broadcast/system/:type

第一个主题用于接收下发给登陆用户的信息。

第二个主题用于接收下发给一个公司下所有用户的信息。

第三个主题用于接收下发给一个公司下一个特定角色下所有用户信息。

第四个主题用于接受系统消息。

以向某一用户推送消息为例,当业务逻辑满足一定条件需要向登陆的某一个用户推送实时消息时,业务系统调用 mqtt broker 的 http API,携带主题和数据,broker 收到后转发给通过 mqtt 协议连接的登录用户的浏览器,进行提示,其他几个主题流程相同

在线聊天

在线聊天分为与系统运营与采购商、供应商聊天,采购商、供应商之间进行聊天两种,实现类似。以用户 A 与用户 B 聊天为例。

用户 A、用户 B 在浏览器登陆后通过 mqtt 协议链接 broker,订阅主题

m2m/company/公司id/role/角色id/user/用户id

当用户 A 发起聊天输入信息并点击发送后,前端调用业务系统提供的 api,业务后段存储消息并调用 broker 的 API,broker 转发该消息到用户 B 登陆的浏览器。用户 B 向用户 A 回复消息仍然是调用业务系统提供的 API,与 A 向 B 发送一致。整个数据流向是 :
在这里插入图片描述

业务系统下发数据与消息推送大致相同,其中前端程序接受消息采用 mqtt 协议,唯一区别是实时聊天用户发送消息时,不使用 mqtt 而是调用业务系统的提供的 http API,业务系统再调用 borker API,borker 转发 这样实现的目的是为了记录用户的聊天数据,

当用户在此进入聊天界面时,可以调用业务系统提供的聊天记录 API,得到之前存储到业务系统中的聊天记录。

其他技术实现方案

业务后台程序与 mqtt broker 的对接另外除上述 htpp 方案外,还可以采用业务后台程序作为 mqtt 客户端接入 mqtt broker 的方式,通配订阅#主题,接受所有客户端发送到设备的信息,然后根据实际主题进行存储、转发等处理。

如果具有二次开发能力,还可以对 Emq 或者 ActiveMq 进行二次开发,实现直接数据入库或者集成到业务系统当中。

以上三种方式,第一种开发最简单,可控性比较强。

broker

mqtt 封装与纯 socket 对比

优点

使用 websocket 的 mqtt 与直接使用 websocket 通信相比,前后台开发工作量能够有效减少,主要有以下几点:

  1. mqtt 自带鉴权,后台 socket 不需要编写登陆验证等逻辑
  2. mqtt 自带 topic,可以实现消息分发,不需要编写群发等复杂程序逻辑
  3. mqtt 自带消息确认功能(qos 1 或者 2),不需要编写消息回传逻辑

缺点

  1. 需要单独在后台独立运行 mqtt broker
  2. 需要增加应用程序与 broker 之间的通信逻辑

可用 mqtt broker

目前可用 broker 有 mosquitto、emqx、activemq 等,下表列出几种对比
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
在这里插入图片描述

<think>好的,用户问的是如何在Spring Boot中集成和配置MQTT客户端。我需要根据提供的引用内容来组织回答。首先,我需要回忆一下Spring Boot集成MQTT的常见方法,尤其是引用的资料里提到的步骤。 首先,引用[1]提到要添加依赖,所以第一步应该是添加Spring Integration MQTT的依赖。我需要确认正确的依赖项,比如groupId和artifactId,可能像org.springframework.integration:spring-integration-mqtt。 接下来,引用[2]和[3]都提到了配置MQTT连接参数,比如服务器地址、客户端ID等。配置通常会放在application.properties或application.yml中,所以需要列出这些配置项,如spring.mqtt.serverUrl、clientId等。 然后,创建配置类,使用@Configuration注解,并定义相关的Bean,比如MqttConnectOptions和ClientManager。引用[2]中的例子使用了Java DSL配置出站适配器,这里可能需要说明如何通过配置类来设置连接选项和客户端工厂。 此外,消息处理部分可能需要使用Spring Integration的通道和处理器,比如使用MqttPahoMessageHandler来处理消息的发布,以及ServiceActivator来处理订阅的消息。用户可能需要了解如何定义入站和出站的适配器,或者使用IntegrationFlow来构建消息流。 另外,引用[2]中的代码示例提到了使用IntegrationFlow和MqttPahoMessageHandler,这部分需要详细说明如何配置出站流,可能还需要提到入站适配器的配置,比如MqttPahoMessageDrivenChannelAdapter。 还需要注意是否需要设置自动重连、保持连接等选项,这些可能在MqttConnectOptions里配置,比如setAutomaticReconnect(true)和setKeepAliveInterval(60)。 最后,可能需要给出一个简单的发布和订阅的示例代码,比如使用@ServiceActivator来处理订阅的消息,以及如何注入MessageHandler来发布消息。 在回答过程中,要确保步骤清晰,先添加依赖,然后配置参数,接着创建配置类,定义Bean,然后处理消息的发布和订阅。同时,要检查是否有遗漏的细节,比如客户端ID的唯一性,或者SSL配置等高级选项是否要提及。 可能还需要提到测试方法,比如如何发送测试消息,或者如何监听主题。另外,要确保所有代码示例符合Spring Boot的最新实践,比如是否使用@Bean注解正确,或者是否需要启用某些功能注解如@EnableIntegration。 最后,生成相关问题的时候,要考虑用户可能的后续问题,比如性能优化、断线处理、多主题订阅等。</think>### 如何在 Spring Boot 中集成与配置 MQTT 客户端 #### 1. 添加依赖 在 `pom.xml` 中添加 Spring Integration MQTT 依赖: ```xml <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-mqtt</artifactId> </dependency> ``` 此依赖提供了 MQTT 协议的核心支持[^1]。 #### 2. 配置连接参数 在 `application.properties` 中配置 MQTT 服务器信息: ```properties # MQTT 服务器地址 spring.mqtt.server-url=tcp://localhost:1883 # 客户端ID(需唯一) spring.mqtt.client-id=spring-boot-client # 用户名和密码(可选) spring.mqtt.username=admin spring.mqtt.password=123456 ``` #### 3. 创建 MQTT 配置类 定义连接选项和客户端工厂: ```java @Configuration public class MqttConfig { @Value("${spring.mqtt.server-url}") private String serverUrl; @Bean public MqttConnectOptions mqttConnectOptions() { MqttConnectOptions options = new MqttConnectOptions(); options.setServerURIs(new String[]{serverUrl}); options.setAutomaticReconnect(true); // 自动重连 options.setKeepAliveInterval(60); // 心跳间隔(秒) return options; } @Bean public MqttPahoClientFactory clientFactory() { DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); factory.setConnectionOptions(mqttConnectOptions()); return factory; } } ``` #### 4. 实现消息发布与订阅 **发布消息配置**: 使用 `MqttPahoMessageHandler` 定义出站通道: ```java @Bean public IntegrationFlow mqttOutboundFlow(MqttPahoClientFactory factory) { return IntegrationFlows.from("mqttOutboundChannel") .handle(new MqttPahoMessageHandler(factory, "publisherClient")) .get(); } ``` **订阅消息配置**: 使用 `MqttPahoMessageDrivenChannelAdapter` 定义入站适配器: ```java @Bean public IntegrationFlow mqttInboundFlow(MqttPahoClientFactory factory) { return IntegrationFlows.from( new MqttPahoMessageDrivenChannelAdapter("subscriberClient", factory, "topic/test")) .channel(MessageChannels.direct("mqttInboundChannel")) .get(); } @ServiceActivator(inputChannel = "mqttInboundChannel") public void handleMessage(Message<?> message) { System.out.println("Received: " + message.getPayload()); } ``` #### 5. 使用示例 注入 `MessageChannel` 发送消息: ```java @Autowired @Qualifier("mqttOutboundChannel") private MessageChannel mqttOutboundChannel; public void sendMessage(String payload) { mqttOutboundChannel.send(MessageBuilder.withPayload(payload).build()); } ``` --- ### 关键配置说明 1. **自动重连**:通过 `options.setAutomaticReconnect(true)` 确保网络中断后自动恢复连接[^2]。 2. **QoS 设置**:可在发布或订阅时指定服务质量等级(0/1/2)。 3. **SSL/TLS 支持**:若需加密通信,可将 `tcp://` 替换为 `ssl://`,并配置密钥库。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值