车间角落的温度传感器想把数据送到值班电脑,网线拉不到,串口又太远。这种「几个不太聪明的设备要互相传话」的场景,物联网领域早就有了约定俗成的答案: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 协议和一堆设备状态的内存表;替不掉的是设备侧的采集代码,传感器怎么读数、怎么组包,还是得你自己写。它只管把消息准确送到,不管消息内容是什么。
核心机制
- 发布订阅加主题匹配。主题用斜杠分层,比如
factory/shop/temp,订阅端可以用factory/#一次收整个车间。通配符是协议层面的能力,不是 Mosquitto 的私有功能(推断:主题分层设计是否合理,比之后调服务器参数更影响扩展性,前期值得多想十分钟)。 - 三档服务质量。QoS 0 是发出去就不管,QoS 1 保证至少到一次(可能重复),QoS 2 保证恰好一次。带电表、计费类数据用 QoS 1 以上,温度这种新值覆盖旧值的用 QoS 0 就够。
- 遗嘱消息。客户端连接时可以预存一条「遗嘱」,一旦异常掉线,Broker 替它把遗嘱发出去。很多人拿这个机制做设备在线状态告警(推断:这也是它常被用来做「设备心跳」的原因,比应用层自己发心跳包省事)。
- 会话保持与持久化。掉线重连的订阅者可以让 Broker 补发离线期间的消息,开启 persistence 后重启服务器消息也不丢。
整条链路长这样:
跑起来
需要一台装了 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,一条消息总线就通了。
从零到能用
- 在宿主机建好
~/mosq目录,写入上面的mosquitto.conf。 - 先用匿名配置启动容器,确认端口 1883 能通、收发测试通过。
- 生成密码文件,并改配置关掉匿名。生成命令:
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。- 用
mosquitto_pub -u dev -P 你的密码重新发一条,确认鉴权生效。 - 在云服务器安全组或路由器端口转发里只放行 1883 给需要的来源地址,再让真实设备接进来。
适合谁用 / 别用
适合三类人:学物联网或电气、想亲手摸一遍 MQTT 协议的学生;手头有几块单片机、几台设备,需要一个稳定消息中转站的人;家里多个自托管程序(监控、备份、通知)想互相喊话的人。一台 512MB 内存的小主机就够它跑很多年。
别用:设备数上万、需要集群、多租户和复杂权限运营的场景,那是 EMQX 这类商业级开源方案的地盘。也别拿它去顶消息队列的活——某些场景它可以替代 RabbitMQ 的部分轻量用途,但替不掉 Kafka 那种磁盘持久化、消息回放和消费组扩缩容,数据量大还是要用专业队列。
三个真实的坑
- 升级到 2.0 之后,什么都不配的话它只监听本机回环地址,而且默认拒绝匿名。README 写得很清楚:直接启动只允许本机匿名访问,想远程连接必须写配置文件定义 listener(README.md Quick start 一节)。这个默认行为的变更也让不少老用户提了 issue(#2515 Minimal config changed without notice)。
- Docker 里改了配置没生效,多半是挂载姿势不对:
-v挂的是单个 conf 文件而不是目录,或者路径写错,容器就静默用回内置默认配置(#2809 Custom mosquitto.conf being ignored under Docker)。挂整个 config 目录最稳。 - 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/
默认评论
Halo系统提供的评论