小岳
2026-11-09
点 赞
0
热 度
3
评 论
0

Mosquitto:十分钟搭起自己的消息总线

  1. 首页
  2. 开源分享
  3. Mosquitto:十分钟搭起自己的消息总线

文章摘要

摸鱼小助手

车间角落的温度传感器想把数据送到值班电脑,网线拉不到,串口又太远。这种「几个不太聪明的设备要互相传话」的场景,物联网领域早就有了约定俗成的答案:MQTT。Mosquitto 就是这个协议最常用的轻量级服务器,C 语言写成,二进制只有几百 KB,一块树莓派甚至一块旧路由器都能跑。今天把它装起来,今晚就能让设备发出第一条消息。

项目名片

项目 内容
仓库 eclipse-mosquitto/mosquitto
star / fork 11346 / 2662(2026-11-09 抓取)
最近提交 2026-11-06
技术栈 C / C++
许可证 EPL-2.0 OR BSD-3-Clause(LICENSE.txt 原文确认)
最新版本 v2.1.2(2026-11-09 抓取)
默认端口 1883

它解决什么问题

设备联网的第一反应是「直接开个 TCP 口传 JSON」,但设备经常掉线、重连,接收端一多,谁轮询谁、谁漏了谁,全靠人肉记账。MQTT 把这事倒过来:所有设备只连一个服务器(叫 Broker),往一个「主题」上发消息,谁关心谁订阅。发送方和接收方互不认识,也不用同时在线。

Mosquitto 就是那个 Broker。它替掉的是你自己写的轮询脚本、私有 TCP 协议和一堆设备状态的内存表;替不掉的是设备侧的采集代码,传感器怎么读数、怎么组包,还是得你自己写。它只管把消息准确送到,不管消息内容是什么。

核心机制

  1. 发布订阅加主题匹配。主题用斜杠分层,比如 factory/shop/temp,订阅端可以用 factory/# 一次收整个车间。通配符是协议层面的能力,不是 Mosquitto 的私有功能(推断:主题分层设计是否合理,比之后调服务器参数更影响扩展性,前期值得多想十分钟)。
  2. 三档服务质量。QoS 0 是发出去就不管,QoS 1 保证至少到一次(可能重复),QoS 2 保证恰好一次。带电表、计费类数据用 QoS 1 以上,温度这种新值覆盖旧值的用 QoS 0 就够。
  3. 遗嘱消息。客户端连接时可以预存一条「遗嘱」,一旦异常掉线,Broker 替它把遗嘱发出去。很多人拿这个机制做设备在线状态告警(推断:这也是它常被用来做「设备心跳」的原因,比应用层自己发心跳包省事)。
  4. 会话保持与持久化。掉线重连的订阅者可以让 Broker 补发离线期间的消息,开启 persistence 后重启服务器消息也不丢。

整条链路长这样:

Mosquitto 发布订阅工作流

跑起来

需要一台装了 Docker 的 Linux 机器(云服务器、NAS、树莓派都行)。先写一份最小配置,本机测试先放开匿名:

mkdir -p ~/mosq/config ~/mosq/data
cat > ~/mosq/config/mosquitto.conf <<'EOF'
listener 1883 0.0.0.0
allow_anonymous true
persistence true
persistence_location /mosquitto/data/
EOF
docker run -d --name mosq -p 1883:1883 \
  -v ~/mosq/config:/mosquitto/config \
  -v ~/mosq/data:/mosquitto/data \
  eclipse-mosquitto:2

注意第一行的 listener 1883 0.0.0.0 不能省,原因见后面第三个坑。起好之后开两个终端互相收发:

IMG=eclipse-mosquitto:2
docker run --rm --network host $IMG \
  mosquitto_sub -h 127.0.0.1 -t 'test/#' -v
IMG=eclipse-mosquitto:2
docker run --rm --network host $IMG \
  mosquitto_pub -h 127.0.0.1 -t test/temp \
  -m "35.6"

订阅那头立刻打印出 test/temp 35.6,一条消息总线就通了。

从零到能用

  1. 在宿主机建好 ~/mosq 目录,写入上面的 mosquitto.conf。
  2. 先用匿名配置启动容器,确认端口 1883 能通、收发测试通过。
  3. 生成密码文件,并改配置关掉匿名。生成命令:
  4. docker run --rm -v ~/mosq/config:/cfg eclipse-mosquitto:2 mosquitto_passwd -c -b /cfg/pwfile dev 你的密码,同时在配置里写入 allow_anonymous false 和 password_file /mosquitto/config/pwfile,然后 docker restart mosq。
  5. 用 mosquitto_pub -u dev -P 你的密码 重新发一条,确认鉴权生效。
  6. 在云服务器安全组或路由器端口转发里只放行 1883 给需要的来源地址,再让真实设备接进来。

适合谁用 / 别用

适合三类人:学物联网或电气、想亲手摸一遍 MQTT 协议的学生;手头有几块单片机、几台设备,需要一个稳定消息中转站的人;家里多个自托管程序(监控、备份、通知)想互相喊话的人。一台 512MB 内存的小主机就够它跑很多年。

别用:设备数上万、需要集群、多租户和复杂权限运营的场景,那是 EMQX 这类商业级开源方案的地盘。也别拿它去顶消息队列的活——某些场景它可以替代 RabbitMQ 的部分轻量用途,但替不掉 Kafka 那种磁盘持久化、消息回放和消费组扩缩容,数据量大还是要用专业队列。

三个真实的坑

  1. 升级到 2.0 之后,什么都不配的话它只监听本机回环地址,而且默认拒绝匿名。README 写得很清楚:直接启动只允许本机匿名访问,想远程连接必须写配置文件定义 listener(README.md Quick start 一节)。这个默认行为的变更也让不少老用户提了 issue(#2515 Minimal config changed without notice)。
  2. Docker 里改了配置没生效,多半是挂载姿势不对:-v 挂的是单个 conf 文件而不是目录,或者路径写错,容器就静默用回内置默认配置(#2809 Custom mosquitto.conf being ignored under Docker)。挂整个 config 目录最稳。
  3. bind-mount 挂进来的 password_file 经常报权限错误:容器内服务跑在非 root 用户下,读不了宿主机生成的密码文件(#3263 [Docker] Permission errors when loading passwordfile with bind-mounts)。给密码文件加读权限,或干脆在容器内生成再拷出来。

小结

回到车间那台温度传感器:装好 Docker,二十行配置,十分钟之后它就能把读数发到值班电脑上了。MQTT 的门槛不在服务器,而在主题设计和 QoS 选择,这些只有亲手跑一遍才有感觉。今晚就起一个,明天写进周报。

参考资料

  • 仓库:https://github.com/eclipse-mosquitto/mosquitto
  • README:https://github.com/eclipse-mosquitto/mosquitto/blob/master/README.md
  • 配置变更 issue:https://github.com/eclipse-mosquitto/mosquitto/issues/2515
  • Docker 配置问题:https://github.com/eclipse-mosquitto/mosquitto/issues/2809
  • 密码文件权限问题:https://github.com/eclipse-mosquitto/mosquitto/issues/3263
  • 官网下载:https://mosquitto.org/download/
  • 鉴权文档:https://mosquitto.org/documentation/authentication-methods/

本站站长,主角光环,怎么滴,你还想攻击你的站长吗,真是好big的狗胆

小岳

intp 逻辑家

站长

不具版权性
不具时效性

文章内容不具时效性。若文章内容有错误之处,请您批评指正。

目录

欢迎来到摸鱼干货栈,这里为您提供开源与摸鱼源码

18 文章数
6 分类数
0 评论数
31标签数
最近评论