Linux 安装 Mosquitto 及 SpringBoot 整合

Linux(centos)下 Mosquitto MQTT 代理的安装与配置

MQTT(Message Queuing Telemetry Transport)是一种轻量级的、基于发布/订阅模式的消息传输协议,广泛应用于物联网(IoT)领域。Mosquitto 是一个开源的 MQTT 代理,它支持 MQTT 协议 3.1 和 3.1.1,适用于各种设备和平台。

在工业上使用 MQTT 协议来进行物联网数据传输,主要看中了以下优点:

  • 低协议开销:它的每消息标题可以短至 2 个字节,容错性好
  • 物联网的网络环境往往比较恶劣,MQTT能从断开故障中恢复,并且不需要额外的编码
  • 低功耗:MQTT专门为了低功耗的目标而设计
  • 最多能接受百万级别的客户端

安装 Mosquitto

安装

选择需要安装的版本,我这里安装的是 2.0.0 版。

官网下载:https://mosquitto.org/files/source/

# 下载
wget --no-check-certificate https://mosquitto.org/files/source/mosquitto-2.0.0.tar.gz

# 安装
tar -zxvf mosquitto-2.0.0.tar.gz

cd mosquitto-2.0.0

make

make install

如果 make 时报如下错误

In file included from mosquitto_ctrl.c:29:
mosquitto_ctrl.h:21:10: fatal error: cJSON.h: No such file or directory
21 | #include <cJSON.h>
|          ^~~~~~~~~
compilation terminated.
make[2]: *** [Makefile:49: mosquitto_ctrl.o] Error 1
make[2]: Leaving directory '/usr/local/mosquitto-2.0.0/apps/mosquitto_ctrl'
make[1]: *** [Makefile:9: all] Error 2
make[1]: Leaving directory '/usr/local/mosquitto-2.0.0/apps'
make: *** [Makefile:64: mosquitto] Error 2

出现 cJSON 找不到,需要安装 cJSON(cJSON-1.7.18.tar.gz):

下载地址:https://github.com/DaveGamble/cJSON/releases

# 安装

tar -zxvf cJSON-1.7.18.tar.gz

cd cJSON-1.7.18

make

make install

cJSON 安装成功后再进行 make 安装即可成功。

相关配置

Mosquitto 的配置文件通常位于:/etc/mosquitto/mosquitto.conf 根据需要修改配置文件中的设置,可以更改监听地址和端口、设置持久化选项、配置用户认证等。

创建配置文件

cp /etc/mosquitto/mosquitto.conf.example /etc/mosquitto/mosquitto.conf

监听端口

一般使用mqtt默认监听端口 1883, 如果需要修改监听端口,需修改配置文件设置自己的端口即可(我这里使用默认的)。

配置用户认证

MQTT 默认无需用户认证,配置 MQTT 的用户名和密码通常涉及编辑 MQTT 代理的配置文件。

Mosquitto 使用 pwfile 来存储用户名和密码,可以使用 mosquitto_passwd 命令来创建和管理这个文件。

# 创建密码文件,用户名称为 mosquittoadmin

mosquitto_passwd -c /etc/mosquitto/pwfile.conf mosquittoadmin

系统会提示输入密码并再次确认,-c 选项表示创建一个新的密码文件。如果文件已经存在,则使用 -b 选项追加用户。

编辑 Mosquitto 配置文件 /etc/mosquitto/mosquitto.conf,添加或修改以下行以启用密码文件认证:

allow_anonymous false

password_file /etc/mosquitto/pwfile

创建 mosquitto 用户

配置文件中默认使用 user mosquitto,需要创建 mosquitto 用户:

groupadd mosquitto

useradd -g mosquitto mosquitto
 
chown -R mosquitto:mosquitto /etc/mosquitto/

设置外网访问

# 设置外网访问
listener 1883 0.0.0.0

启动、查看、关闭程序

运行程序

mosquitto -c /etc/mosquitto/mosquitto.conf -d

查看

ps -aux | grep mosquitto

关闭程序

kill -9 $(pidof mosquitto)

SpringBoot 整合 Mosquitto

添加依赖

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

配置 MQTT 服务器的连接信息

server:
  port: 8001

mqtt:
  url: tcp://127.0.0.1:1883
  username: mosquittoadmin
  password: mosquittoadmin@123
  client-id: test-client

MQTT 配置类

package com.demo.config;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @path:com.demo.config.MqttClientConfig.java
 * @className:MqttClientConfig.java
 * @description: MQTT配置
 * @dateTime:2025/1/5 10:51 
 * @editNote:
 */
@Configuration
public class MqttClientConfig {

    @Value("${mqtt.url}")
    private String url;

    @Value("${mqtt.client-id}")
    private String clientId;

    @Value("${mqtt.username}")
    private String username;

    @Value("${mqtt.password}")
    private String password;

    @Bean
    public MqttClient mqttClient() throws MqttException {
        MqttClient client = new MqttClient(url, clientId);
        MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        client.connect(options);
        return client;
    }

}

发布、订阅消息

package com.demo.service;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @path:com.demo.service.MqttService.java
 * @className:MqttService.java
 * @description: 发布、订阅消息
 * @dateTime:2025/1/5 10:51 
 * @editNote:
 */
@Slf4j
@Service
public class MqttService {

    @Autowired
    private MqttClient mqttClient;

    /**
     * @MonthName: publish
     * @Description: 发布消息
     * @Date: 2025/1/5 11:26
     * @Param: [topic, message]
     * @return: void
     **/
    public void publish(String topic, String message) throws MqttException {
        log.info("===发布消息====topic:{},消息内容:{}", topic, message);
        MqttMessage mqttMessage = new MqttMessage(message.getBytes());
        mqttMessage.setQos(2);
        mqttClient.publish(topic, mqttMessage);
    }

    /**
     * @MonthName: subscribe
     * @Description: 订阅消息
     * @Date: 2025/1/5 11:26
     * @Param: [topic]
     * @return: void
     **/
    public void subscribe(String topic) throws MqttException {
        mqttClient.subscribe(topic, (t, msg) -> {
            String message = new String(msg.getPayload());
            log.info("===订阅消息====topic:{},消息内容:{}", topic, message);
        });
    }

}

** MqttController 接口**

package com.demo.controller;

import com.demo.service.MqttService;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/mqtt")
public class MqttController {

    @Autowired
    private MqttService mqttService;

    @GetMapping("/publish")
    public String publish(@RequestParam String topic, @RequestParam String message) {
        try {
            mqttService.publish(topic, message);
            log.info("发布消息,topic:{},消息内容:{}", topic, message);
            return "success";
        } catch (MqttException e) {
            log.error("{}", e);
            return "error";
        }
    }

    @GetMapping("/subscribe")
    public String subscribe(@RequestParam String topic) {
        try {
            mqttService.subscribe(topic);
            log.info("订阅消息,topic:{}", topic);
            return "success";
        } catch (MqttException e) {
            log.error("{}", e);
            return "error";
        }
    }

}

初始化订阅消息

服务初始化启动完成后,自动订阅 Topic

package com.demo.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @path:com.demo.service.SubscribeRunner.java
 * @className:SubscribeRunner.java
 * @description: 初始化订阅消息
 * @dateTime:2025/1/5 15:25 
 * @editNote:
 */
@Slf4j
@Component
@Order(10)
public class SubscribeRunner implements ApplicationRunner {

    @Autowired
    MqttService mqttService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("================初始化订阅消息==================");
        mqttService.subscribe("mytopic");
    }
}

启动服务测试

启动服务

Connected to the target VM, address: '127.0.0.1:52517', transport: 'socket'

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.9)

2025-01-05 21:28:00.464  INFO 8888 --- [           main] com.demo.DemoBootApplication               : Starting DemoBootApplication using Java 1.8.0_251 on DESKTOP-BBRENPM with PID 8888 (E:\workspace\demo-boot\target\classes started by Administrator in E:\workspace\demo-boot)
2025-01-05 21:28:00.466  INFO 8888 --- [           main] com.demo.DemoBootApplication               : No active profile set, falling back to 1 default profile: "default"
2025-01-05 21:28:00.949  INFO 8888 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8001 (http)

自动订阅消息,可以通过请求接口手动订阅:http://localhost:8001/mqtt/subscribe?topic=mytopic

2025-01-05 21:28:01.666  INFO 8888 --- [           main] com.demo.DemoBootApplication               : Started DemoBootApplication in 1.427 seconds (JVM running for 1.932)
2025-01-05 21:28:01.667  INFO 8888 --- [           main] com.demo.service.SubscribeRunner          : ================初始化订阅消息==================
2025-01-05 21:28:16.428  INFO 8888 --- [nio-8001-exec-1] o.a.c.c.C.[.[localhost]        : Initializing Spring DispatcherServlet 'dispatcherServlet'
2025-01-05 21:28:16.428  INFO 8888 --- [nio-8001-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2025-01-05 21:28:16.428  INFO 8888 --- [nio-8001-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms

发布消息,浏览器访问接口:

http://localhost:8001/mqtt/publish?message=测试消息

2025-01-05 21:29:34.603  INFO 8888 --- [nio-8001-exec-8] com.demo.controller.MqttController        : 发布消息,topic:mytopic,消息内容:测试消息

2025-01-05 21:29:34.613  INFO 8888 --- [ll: test-client] com.demo.service.MqttService              : ===订阅消息====topic:mytopic,消息内容:测试消息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/950096.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

刚体变换矩阵的逆

刚体运动中的变换矩阵为&#xff1a; 求得变换矩阵的逆矩阵为&#xff1a; opencv应用 cv::Mat R; cv::Mat t;R.t(), -R.t()*t

IDEA中Maven依赖包导入失败报红的潜在原因

在上网试了别人的八个问题总结之后依然没有解决&#xff1a; IDEA中Maven依赖包导入失败报红问题总结最有效8种解决方案_idea导入依赖还是报红-CSDN博客https://blog.csdn.net/qq_43705131/article/details/106165960 江郎才尽之后突然想到一个原因&#xff1a;<dep…

UVM:uvm_component methods configure

topic UVM component base class uvm_config_db 建议使用uvm_config_db代替uvm_resource_db uvm factory sv interface 建议&#xff1a;uvm_config_db 以下了解 建议打印error

基于时间维度水平拆分的多 TiDB 集群统一数据路由/联邦查询技术的实践

导读 在大数据时代&#xff0c;金融行业面临着日益增长的数据量和复杂的查询需求&#xff0c;尤其是跨库、跨集群的场景。在这种背景下&#xff0c;如何在保证数据一致性、高可用性的同时&#xff0c;实现业务的快速扩展与高效查询&#xff0c;成为了企业数字化转型的关键挑战…

概率论 期末 笔记

第一章 随机事件及其概率 利用“四大公式”求事件概率 加法公式 减法 条件概率公式 全概率公式与贝叶斯公式 伯努利概型求概率 习题 推导 一维随机变量及其分布 离散型随机变量&#xff08;R.V&#xff09;求分布律 利用常见离散型分布求概率 连续型R.V相关计算 利用常见连续…

把vue项目或者vue组件发布成npm包或者打包成lib库文件本地使用

将vue项目发布成npm库文件&#xff0c;第三方通过npm依赖安装使用&#xff1b;使用最近公司接了一个项目&#xff0c;这个项目需要集成到第三方页面&#xff0c;在第三方页面点击项目名称&#xff0c;页面变成我们的项目页面&#xff1b;要求以npm库文件提供给他们&#xff1b;…

《空舞的巨兽》官方学习版

一个以被遗忘之地为背景的原创故事&#xff0c;这是一个充满悲剧的没落王国。扮演外地战士雷恩猎人&#xff08;玩家&#xff09;&#xff0c;踏上危险的任务&#xff0c;结束困扰你自己和村庄的诅咒。你唯一的希望就是杀死不可杀死的可怕巨兽。 《空舞的巨兽》官方版 https:/…

go-zero框架快速入门

文章目录 go-zero 简介安装goctl安装go-zero启动go-zero API语言定义结构体API定义路由API格式化对齐 生成代码生成基本逻辑代码生成数据库model文件 go-zero 简介 go-zero 是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性&#xff0c;经…

切忌 SELECT *,就算表只有一列

原文地址 尽量避免 SELECT *&#xff0c;即使在单列表上也是如此 – 如果你现在不同意这一点&#xff0c;读完这篇文章&#xff0c;你可能就要动摇了。 2012年的一个故事 这是我 12 年前&#xff08;约 2012-2013 年&#xff09;在客户后台应用程序中遇到的一个真实故事。 当…

了解RabbitMQ中的Exchange:深入解析与实践应用

在分布式系统设计中&#xff0c;消息队列&#xff08;Message Queue&#xff09;扮演着至关重要的角色&#xff0c;而RabbitMQ作为开源消息代理软件的佼佼者&#xff0c;以其高性能、高可用性和丰富的功能特性&#xff0c;成为了众多开发者的首选。在RabbitMQ的核心组件中&…

【linux系统之redis6】redis的基础命令使用及springboot连接redis

redis的基础命令很多&#xff0c;大部分我们都可以在官网上找到&#xff0c;真的用的时候可以去官网找&#xff0c;不用全部记住这些命令 redis通用的基础命令的使用 代码测试 string类型常见的命令 key值的结构&#xff0c;可以区分不同的需求不同的业务名字 hash类型 创建…

基于FPGA的交通信号灯实现 (verilog极简实现)

本文分享利用FPGA实现的交通信号灯&#xff0c;FPGA型号为野火征途Pro开发板&#xff0c;具体功能如下&#xff1a; 此项目旨在模拟东西和南北两路口交通信号灯&#xff0c;初始态两路口均为红灯亮&#xff0c;接着&#xff0c;东西路口绿灯亮&#xff0c;南北路口红灯亮&…

在K8S上部署OceanBase的最佳实践

在K8S上部署OceanBase的最佳实践 目录 1. 背景与选型 1.1 为什么选择OB1.2 为什么选择ob-operator实现OB on K8S 2. 部署实操 2.1 环境准备2.2 安装 ob-operator2.3 配置 OB 集群2.4 配置 OBProxy 集群2.5 Headless Service 和 CoreDNS 配置2.6 监控与运维 2.6.1 Promethues部…

unity开发之shader 管道介质流动特效

效果 shader graph 如果出现下面的效果&#xff0c;那是因为你模型的问题&#xff0c;建模做贴图的时候没有设置好UV映射&#xff0c;只需重新设置下映射即可

【JavaWeb】2. 通用基础代码

以下内容来源&#xff1a;编程导航。 无论在任何后端项目中&#xff0c;都可以复用的代码。 1、自定义异常 自定义错误码&#xff0c;对错误进行收敛&#xff0c;便于前端统一处理。 &#x1f4a1; 这里有 2 个小技巧&#xff1a; 自定义错误码时&#xff0c;建议跟主流的错…

Excel 技巧04 - 如何计算两个时间之差 (★)

本文讲了如何通过Excel计算两个时间的时间差。 1&#xff0c;计算两个时间的时间差 比如 5&#xff1a;50 ~ 19&#xff1a;40 a&#xff09;&#xff0c;用公式 相减 这样默认算出来的是机械的时间加减&#xff0c;即它们之间相差了 13小时50分钟 b&#xff09;&#xff0c;…

win下搭建elk并集成springboot

一、ELK 是什么&#xff1f; ELK 实际上是三个工具的集合&#xff0c;Elasticsearch Logstash Kibana&#xff0c;这三个工具组合形成了一套实用、易用的监控架构&#xff0c;很多公司利用它来搭建可视化的海量日志分析平台。 ElasticSearch ElasticSearch 是一个基于 Lucen…

JUC--线程池

线程池 七、线程池7.1线程池的概述7.2线程池的构建与参数ThreadPoolExecutor 的构造方法核心参数线程池的工作原理 Executors构造方法newFixedThreadPoolnewCachedThreadPoolnewSingleThreadExecutornewScheduledThreadPool(int corePoolSize) 为什么不推荐使用内置线程池&…

Java到底是值传递还是引用传递????

在搞懂这个问题之前, 我们要首先了解什么是值传递, 什么是引用传递? 值传递: 传递的是数据的副本&#xff0c;修改副本不会影响原始数据。引用传递: 传递的是数据的引用&#xff08;地址&#xff09;&#xff0c;修改引用会直接影响原始数据. 也就是说&#xff0c;值传递和引…

屏幕显示技术再突破!海信RGB- Mini LED,让色彩“活”起来

文 | 智能相对论 作者 | 佘凯文 在今天&#xff0c;屏幕显示技术的日新月异&#xff0c;让每次技术革新都引领行业迈向新的高度。 从黑白到彩色&#xff0c;从标清到高清&#xff0c;再到超高清&#xff0c;回顾曾经彩电显示的技术升级&#xff0c;不仅都极大地提升了观众的…