MQTT协议---EMQX基础应用~~~

一、前言

在物联网项目中必不可少使用mqtt协议,不同平台、终端设备都要使用mqtt交互数据,但是mqtt协议的使用必然会涉及到mqtt的broker的使用,和数据持久化。

二、MQTT协议

1、简介
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅模式的"轻量级"通讯协议,它和 Modbus TCP 一样都是基于 TCP/IP 之上的应用层协议。
物联网设备通信有一些问题需要针对性的解决:网络环境复杂而不可靠、硬件内存和闪存容量小、处理器能力有限。MQTT 协议就是为了解决遇到的这些问题而创建的;
MQTT 最小报文仅为 2 个字节,比 HTTP 占用更少网络开销,MQTT 基于发布订阅模式,HTTP 基于请求响应。
在这里插入图片描述
MQTT消息队列的很多行为和特性非常接近, 比如都采用发布/订阅模式,但是他们面向的场景却 有着显著的不同。消息队列主要用于服务端应用之间的消息存储与转发,这类场景往往数据量大但客户端 数量少。MQTT 是一种消息传输协议,主要用于物联网设备之间的消息传递,这类场景的特点是海量的设备接入、管理与消息传输。

2、MQTT消息服务质量等级
MQTT协议可以对消息设置三种不同的服务质量等级,分别是:
1)QoS=0:最多发送一次,订阅方不会发送接收到消息的响应,发布方也不会重新发送消息,消息可能会丢失;
在这里插入图片描述
2)QoS=1:最少发送一次,订阅方接收到消息之后发送响应给发布方,如果发布方没收到响应会重新发送消息,直到接收到响应为止,消息可能会重复;
在这里插入图片描述
3)QoS=2:保证只有一次,订阅方不会重复接收到消息,也不会丢失消息。发布方和订阅方之间需要进行两次请求响应确认消息传输,保证相同消息只接收一次,QoS为2时消耗网络资源也最多;
在这里插入图片描述
3、MQTT 主题通配符
MQTT 通配符包含单层通配符 + 和多层通配符#,主要用于客户端一次订阅多个主题。在发布的时候不能用通配符下发到多个主题中;
单层通配符适用于单个主题层级匹配的通配符,单层通配符必须占据整个层级才能生效;
在这里插入图片描述
多层通配符适用于主题匹配任意层级的通配符,多层通配符表示它的父级和任意数量的子层级,多层通配符必须单独占据一个层级才能生效;
在这里插入图片描述

三、EMQX简介

EMQX 是一款「无限连接,任意集成,随处运行」的大规模分布式物联网接入平台,同时作为一个高性能、可扩展的 MQTT 消息服务器,它可以为物联网(IoT)应用提供可靠的实时消息传输和设备连接解决方案。

EMQX官网:https://docs.emqx.com/

版本:
EMQX分为开源版本和企业版本,我们主要分享开源版本的使用,会话持久化是 EMQX 企业版功能
在这里插入图片描述
会话和持久存储:

  • 会话:会话是 EMQX 为每个客户端连接创建的轻量级进程。会话负责执行 MQTT
    标准中对消息服务器(broker)所要求的行为。这些行为包括初始连接、订阅和取消订阅主题以及消息分发。
  • 持久存储:持久存储是 EMQX 内部使用的数据库。会话可以利用持久存储保存其状态和发送到主题的 MQTT消息。支持持久存储的数据库引擎使用 RocksDB 将数据保存到磁盘,并通过 Raft 在集群中一致地复制数据。需要注意的是,持久存储持久会话 是不同的概念。

四、EMQX环境搭建

1、运行以下命令获取 Docker 镜像:

  • docker pull emqx/emqx:5.8.0

2、启动容器

docker run -d --name emqx \
  -p 1883:1883 -p 8083:8083 \
  -p 8084:8084 -p 8883:8883 \
  -p 18083:18083 \
  -v $PWD/data:/opt/emqx/data \
  -v $PWD/log:/opt/emqx/log \
  emqx/emqx:5.8.0

3、mqttx客户端

下载地址:https://mqttx.app/zh/downloads
在这里插入图片描述

4、功能验证
数据发送:
在这里插入图片描述
数据接收:
在这里插入图片描述

五、springboot集成

pom.xml依赖

<dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.2</version>
        </dependency>

Producer.java

package com.sk.proxytest.mqtt;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

//@Configuration
public class Producer {

    @PostConstruct
    private void producer(){
        String pubTopic = "testtopic";
        String content = "Hello World";
        int qos = 2;
        String broker = "tcp://159.75.225.251:1883";
        String clientId = "emqx_test";
        MemoryPersistence persistence = new MemoryPersistence();

        try {
            MqttClient client = new MqttClient(broker, clientId, persistence);

            // MQTT 连接选项
            MqttConnectOptions connOpts = new MqttConnectOptions();
            connOpts.setUserName("emqx_test");
            connOpts.setPassword("emqx_test_password".toCharArray());
            // 保留会话
            connOpts.setCleanSession(true);

            // 设置回调
            client.setCallback(new OnMessageCallback());

            // 建立连接
            System.out.println("Connecting to broker: " + broker);
            client.connect(connOpts);

            // 消息发布所需参数
            MqttMessage message = new MqttMessage(content.getBytes());
            message.setQos(qos);
            client.publish(pubTopic, message);
            System.out.println("Message published");

            client.disconnect();
            System.out.println("Disconnected");
            client.close();
            System.exit(0);
        } catch (MqttException me) {
            System.out.println("reason " + me.getReasonCode());
            System.out.println("msg " + me.getMessage());
            System.out.println("loc " + me.getLocalizedMessage());
            System.out.println("cause " + me.getCause());
            System.out.println("excep " + me);
            me.printStackTrace();
        }
    }

}

程序执行结果:

2024-09-08 17:24:48.479  INFO 14732 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 919 ms
Connecting to broker: tcp://159.75.225.251:1883
Message published
deliveryComplete---------true
Disconnected

消费工具:
在这里插入图片描述
Consumer.java

package com.sk.proxytest.mqtt;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

//@Configuration
public class Consumer {

    @PostConstruct
    private void producer(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                test();
            }
        }).start();

    }

    public void test(){
        String subTopic = "testtopic";
        String broker = "tcp://159.75.225.251:1883";
        String clientId = "emqx_test2";
        MemoryPersistence persistence = new MemoryPersistence();

        try {
            MqttClient client = new MqttClient(broker, clientId, persistence);

            // MQTT 连接选项
            MqttConnectOptions connOpts = new MqttConnectOptions();
            connOpts.setUserName("emqx_test");
            connOpts.setPassword("emqx_test_password".toCharArray());
            // 保留会话
            connOpts.setCleanSession(true);

            // 设置回调
            client.setCallback(new OnMessageCallback());

            // 建立连接
            System.out.println("Connecting to broker: " + broker);
            client.connect(connOpts);

            while (true) {
                try {
                    client.subscribe(subTopic);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        } catch (MqttException me) {
            System.out.println("reason " + me.getReasonCode());
            System.out.println("msg " + me.getMessage());
            System.out.println("loc " + me.getLocalizedMessage());
            System.out.println("cause " + me.getCause());
            System.out.println("excep " + me);
            me.printStackTrace();
        }
    }

}

程序执行结果:

2024-09-08 17:26:40.446  INFO 10460 --- [           main] com.sk.proxytest.ProxyTestApplication    : Started ProxyTestApplication in 2.076 seconds (JVM running for 3.006)
接收消息主题:testtopic
接收消息Qos:0
接收消息内容:{
  "msg": "hello1111"
}
接收消息主题:testtopic
接收消息Qos:0
接收消息内容:{
  "msg": "hello1111"
}

注:在实际应用中可以使用mqtt连接创建工厂或者连接池

----------------------------------👇👇👇注:更多信息请关注公众号获取👇👇👇-------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dylan~~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值