7685 字
38 分钟
Mosquitto MQTT Broker 生产就绪部署指南

1. MQTT 协议与 Mosquitto 简介#

1.1 MQTT 协议核心概念#

MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅模式的轻量级物联网通信协议,由 IBM 于 1999 年发明。它运行在 TCP/IP 之上,采用二进制格式,协议头最小仅 2 字节,特别适合带宽受限、网络不稳定的物联网场景。

核心概念:

发布/订阅模型

MQTT 解耦了消息生产者和消费者。设备(客户端)不直接通信,而是通过中心节点 Broker 路由消息。发布者将消息发送到特定”主题”,订阅者从该主题接收消息。这种架构让设备无需知道彼此的存在。

主题

主题是消息的分类标签,使用 / 分层,如 building/floor1/temperature。订阅时支持通配符:

  • +:匹配单层,如 building/+/temperature 匹配所有楼层的温度主题
  • #:匹配多层,如 building/# 匹配该楼栋下所有主题

QoS(服务质量)

MQTT 提供三级服务质量:

QoS名称语义适用场景
0最多一次消息发出去就忘,不保证到达高频传感器数据,丢失一两条无影响
1至少一次确保到达,但可能重复重要但可去重的数据
2恰好一次严格保证不丢不重计费、控制指令

QoS 是逐跳的——发布者到 Broker 和 Broker 到订阅者可以不同。

保留消息

发布时设置 retain=true,Broker 会存储该主题最后一条保留消息。新客户端订阅时立即收到这条消息,无需等待下次发布。典型用途:设备上线时获取最新配置或状态。

遗嘱消息

客户端连接时可设置遗嘱消息。一旦 Broker 检测到该客户端异常断连(心跳超时),自动发布遗嘱消息到指定主题。用于感知设备离线状态。

1.2 Mosquitto 特点与适用场景#

Mosquitto 是 Eclipse 基金会旗下的开源 MQTT Broker,C 语言编写,是业界最广泛使用的 MQTT 实现之一。

核心优势:

  • 极轻量:二进制体积小(< 500KB),内存占用低(万级连接仅需几十 MB)
  • 单机性能优异:单节点可支撑数万到十万级并发连接
  • 完全支持 MQTT 3.1 / 3.1.1 / 5.0 协议
  • 桥接功能:通过 MQTT Bridge 实现跨机房消息同步
  • 配置简单:单一配置文件,学习曲线平缓

局限:

  • 无原生集群:不支持多节点组成逻辑集群,桥接只是消息转发而非真正集群
  • 水平扩展困难:无法像 Kafka 那样通过加节点线性扩展
  • 无内置持久化到外部存储:持久化依赖本地磁盘,不支持直接写入数据库

适用场景: 设备数在 10 万以下的单机部署;跨机房通过桥接实现消息同步;对集群和高可用不敏感的内部系统。

2.1 版本更新: 2026 年 2 月 Eclipse Mosquitto 2.1 正式发布(截至本文撰写时最新为 2.1.2),带来多项重大变化:内置 Web UI(浏览器端直接管理连接与主题)、全新 C 插件系统(替代旧版 auth_plugin 架构)、内置 WebSocket(无需编译时指定 WITH_WEBSOCKETS)、增强 TLS 1.3 支持等。本指南主要基于 2.0.x 编写,所有配置在 2.0.x 上均可直接使用。若使用 2.1,部分章节需注意差异,文中会以 “2.1 提示” 形式标注。

1.3 生产环境架构抉择#

单节点部署(设备 < 1 万)

最简单的部署形态。一台服务器运行 Mosquitto,所有设备直连。配合 TLS 加密和 ACL 权限控制,满足大部分中小规模场景。

优点:部署运维简单,无一致性问题。缺点:单点故障,服务器宕机则所有设备断连。

桥接双活(跨机房高可用)

两台 Mosquitto 分别在两个机房,通过双向 Bridge 互相同步消息。客户端就近连接,单机房故障不影响整体服务。

[机房 A] [机房 B]
Clients ←→ Mosquitto A ←→ Mosquitto B ←→ Clients
↕ ↕
本地消息 本地消息

配置要点:topic 映射避免消息环路(设置 bridge_attempt_unsubscribe 等参数);桥接链路同样启用 TLS 加密。

何时切换到 EMQX / VerneMQ

出现以下信号时,考虑迁移到集群型 Broker:

  • 设备量突破 10 万,单机 Mosquitto 连接数和内存成为瓶颈
  • 需要真正的集群:多节点共享订阅、消息在集群内自动路由
  • 需要数据桥接到 Kafka / PostgreSQL / ClickHouse 等外部系统(Mosquitto 桥接只能到另一个 MQTT Broker)
  • 需要 Web 管理界面、REST API 管理、多租户等企业特性

EMQX 和 VerneMQ 都支持水平扩展的集群架构,内置数据桥接和规则引擎,但运维复杂度也相应上升。

2. 部署前准备#

2.1 硬件与系统要求#

规模CPU内存磁盘
少量设备(< 1000)1-2 核512MB-1GB20GB SSD
中等规模(1000-10000)2-4 核2-4GB50GB SSD
大规模(10000-100000)4-8 核8-16GB100GB+ SSD

文件描述符限制

每个 MQTT 连接消耗一个文件描述符。Linux 默认 1024 远远不够。

Terminal window
# 查看当前限制
ulimit -n
# 永久修改 /etc/security/limits.conf
echo "* soft nofile 100000" >> /etc/security/limits.conf
echo "* hard nofile 100000" >> /etc/security/limits.conf

2.2 端口规划与防火墙策略#

端口协议用途
1883MQTT TCP默认不加密通信(生产环境建议禁用)
8883MQTT over TLS标准加密通信端口
9001MQTT over WebSocket浏览器端需要时启用

防火墙示例(firewalld):

Terminal window
firewall-cmd --permanent --add-port=8883/tcp
firewall-cmd --permanent --add-port=9001/tcp # 按需
firewall-cmd --reload

云环境安全组规则: 仅开放 8883 端口给设备网段;1883 端口除非有充分理由,否则直接禁用。

2.3 域名与 TLS 证书准备#

Let’s Encrypt(公网环境):

/etc/letsencrypt/live/mqtt.example.com/
# 使用 certbot 获取证书
certbot certonly --standalone -d mqtt.example.com

内部 CA(企业内网环境):

自建 CA 签发证书,所有设备预置 CA 根证书。适合设备不访问公网的纯内网场景。

自签名证书(测试环境):

Terminal window
openssl req -new -x509 -days 3650 -nodes \
-out /etc/mosquitto/certs/server.crt \
-keyout /etc/mosquitto/certs/server.key

生产环境务必使用正式 CA 签名证书,避免所有设备都需要配置忽略证书验证。

3. 安装 Mosquitto#

3.1 方式一:系统包管理器安装(推荐)#

Ubuntu / Debian:

Terminal window
# 添加官方 PPA(获取最新稳定版)
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt update
sudo apt install -y mosquitto mosquitto-clients

RHEL / Rocky / AlmaLinux:

Terminal window
# EPEL 仓库包含 mosquitto
sudo dnf install -y epel-release
sudo dnf install -y mosquitto mosquitto-clients

RHEL 9 / Rocky 9 可直接使用 CodeReady Linux Builder 仓库中的版本。如需最新版,可从 mosquitto.org 下载 RPM 包。

2.1 提示: 截至本文撰写时,PPA 和 EPEL 仓库仍提供 2.0.x 版本。如需 2.1,可从源码编译或使用 Docker 镜像(见 3.2 节)。

3.2 方式二:Docker 容器化部署#

docker-compose.yml
version: "3.8"
services:
mosquitto:
image: eclipse-mosquitto:2.0
container_name: mosquitto
restart: unless-stopped
ports:
- "8883:8883"
- "9001:9001" # WebSocket(2.1 内置支持)
volumes:
- ./config/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro
- ./certs:/mosquitto/certs:ro
- mosquitto-data:/mosquitto/data
- mosquitto-log:/mosquitto/log
user: "1883:1883" # mosquitto 镜像内置用户
volumes:
mosquitto-data:
mosquitto-log:

启动:

Terminal window
docker compose up -d

Docker 部署的优点:环境隔离、快速迁移、版本固定。注意:挂载配置文件和证书目录的权限必须让 uid 1883 可读。

2.1 提示:image: eclipse-mosquitto:2.0 替换为 image: eclipse-mosquitto:2.1 即可获取 2.1 版本。2.1 镜像内置 Web UI(默认端口 8080),如需启用可通过环境变量或额外端口映射暴露。

3.3 方式三:源码编译#

仅当需要打自定义补丁或启用实验性功能时使用。

Terminal window
# 安装编译依赖
sudo apt install -y build-essential libssl-dev libc-ares-dev uuid-dev cmake
# 下载并编译(以 2.1.2 为例)
wget https://mosquitto.org/files/source/mosquitto-2.1.2.tar.gz
tar xzf mosquitto-2.1.2.tar.gz
cd mosquitto-2.1.2
make WITH_TLS=yes WITH_WEBSOCKETS=yes
sudo make install

2.1 提示:(注:2.0.x 版本需显式指定 WITH_WEBSOCKETS=yes;2.1.x 版本此选项默认为开启,但显式指定可增强可读性。libwebsockets-dev 在 2.1 中变为可选依赖。)

编译后可执行文件在 /usr/local/sbin/mosquitto,需要手动创建 systemd 服务文件。

3.4 安装后验证#

Terminal window
# 检查版本
mosquitto -h | head -1
# 最简单的功能测试
# 终端1:启动 Broker(前台模式)
mosquitto -v
# 终端2:发布消息
mosquitto_pub -t "test/hello" -m "world"
# 终端3:订阅消息
mosquitto_sub -t "test/#" -v

如果订阅端收到 test/hello world,说明 Broker 正常工作。

4. 核心配置与安全加固#

4.1 基础参数#

/etc/mosquitto/mosquitto.conf
# 进程管理
pid_file /var/run/mosquitto/mosquitto.pid
# 日志
log_dest file /var/log/mosquitto/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information
connection_messages true
# 持久化
persistence true
persistence_location /var/lib/mosquitto/
autosave_interval 300 # 每5分钟自动保存一次持久化状态
  • connection_messages true:记录客户端连接/断连事件,排查问题必备
  • autosave_interval:过短增加磁盘 IO,过长增加重启后消息丢失风险。300s(5分钟)是实践中的平衡值

4.2 网络监听与协议#

仅内网监听(安全推荐):

# 仅监听内网 IP,拒绝外部直连
bind_address 10.0.0.5

禁用不加密端口,强制 TLS:

不配置 listener 1883 即可。只开放 TLS 端口,杜绝明文传输风险。

WebSocket 配置(可选):

listener 9001
protocol websockets
# 如需 TLS 加密的 WebSocket,使用另一端口:
# listener 9002
# protocol websockets
# certfile /etc/mosquitto/certs/server.crt
# keyfile /etc/mosquitto/certs/server.key

4.3 TLS/SSL 加密#

# TLS 监听器
listener 8883
protocol mqtt
# 证书配置
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
cafile /etc/mosquitto/certs/ca.crt # CA 证书链(Let's Encrypt 使用 fullchain.pem)
# 强制客户端使用 TLS
require_certificate false # false = 单向认证(服务端向客户端证明身份)
# true = 双向认证(客户端也需提供证书)
# 仅允许 TLS 1.2+
tls_version tlsv1.2
# 推荐加密套件
ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384

单向认证 vs 双向认证:

  • 单向(require_certificate false):仅客户端验证服务端,适合用户名密码认证场景
  • 双向(require_certificate true):双方互相验证,需为每个设备签发客户端证书,安全性最高但证书管理成本大

生产环境如果设备端能安全存储证书,推荐双向认证;如果设备能力有限,单向 TLS + 用户名密码也是可接受方案。

4.4 认证后端选择#

密码文件(适合少量设备):

password_file /etc/mosquitto/passwd

使用 mosquitto_passwd 工具管理(详见第 5 章)。

动态认证插件(适合大规模设备):

Mosquitto 从 2.0 版本起支持动态认证插件。可以对接 HTTP API、MySQL、Redis 等后端,实现用户认证的集中管理和动态更新。

# 使用 mosquitto-go-auth 插件
auth_plugin /usr/lib/mosquitto-go-auth.so
auth_opt_backends http
auth_opt_http_host http://auth.internal:8080
auth_opt_http_path /auth
auth_opt_http_aclcheckpath /acl

动态认证的优点:无需重启 Mosquitto 即可添加/修改/删除用户;与现有用户系统集成;支持 JWT、OAuth2 等现代认证方式。

4.5 ACL 权限控制#

acl_file /etc/mosquitto/acl

ACL(Access Control List)控制谁可以发布/订阅哪些主题。核心原则:最小权限——设备只能在自己需要的主题上操作。

# 最小权限模板示例
# 每个设备只允许操作自己的主题前缀
# 普通传感器设备:只能上报数据
user sensor_001
topic write devices/sensor_001/telemetry/#
topic read devices/sensor_001/config/#
# 控制网关:可以发送指令
user gateway_001
topic read devices/+/telemetry/#
topic write devices/+/commands/#
# 运维管理员:全局读写
user admin
topic readwrite #
# 禁止所有用户访问系统主题
pattern readwrite $SYS/#

user 针对具体用户名;pattern 针对匹配用户名的模式(如 pattern readwrite devices/%u/# 允许每个用户操作自己的主题)。%u 自动替换为当前用户名。

5. 用户与权限管理实战#

5.1 使用 mosquitto_passwd 管理密码文件#

密码文件使用 mosquitto_passwd 工具管理。每条记录一行,格式为 username:password_hash

Terminal window
# 首次创建密码文件(使用 -c 参数)
mosquitto_passwd -c /etc/mosquitto/passwd sensor_001
# 添加新用户(注意:不要再加 -c,否则会覆盖已有文件)
mosquitto_passwd /etc/mosquitto/passwd sensor_002
# 修改密码(覆盖已存在的用户)
mosquitto_passwd /etc/mosquitto/passwd sensor_001
# 删除用户
mosquitto_passwd -D /etc/mosquitto/passwd sensor_002
# 查看已加密的密码文件(密码已哈希,不可逆)
cat /etc/mosquitto/passwd

常见问题: 误用 -c 覆盖已有密码文件导致所有用户丢失。建议用版本控制备份密码文件,或在变更前 cp 备份。

5.2 ACL 文件编写规范#

ACL 文件的规则从上到下匹配,命中即停止。权限关键字:

关键字含义
read允许订阅
write允许发布
readwrite允许订阅和发布
deny显式拒绝

user 与 pattern 的区别:

  • user <username>:精确匹配用户名
  • pattern <pattern>:匹配模式,支持 %u(用户名)和 %c(客户端 ID)
# 典型场景 1:设备遥测上报
user sensor_001
topic write devices/sensor_001/telemetry/#
topic read devices/sensor_001/commands/#
# 典型场景 2:使用 pattern 实现每个用户操作自己的主题空间
pattern readwrite devices/%u/#
# 典型场景 3:状态查询(设备可以读取全局状态但不能写入)
user status_monitor
topic read devices/+/status/#
topic deny write #
# 典型场景 4:控制指令下发(应用后端)
user backend_service
topic read devices/+/telemetry/#
topic write devices/+/commands/#
# 全局禁止:禁止访问系统内部主题
pattern deny $SYS/#

通配符说明: ACL 中的 # 匹配所有子主题,相当于”允许该前缀下的一切”。如果需要对单个通配符做更精细的控制,逐一列出主题路径。

5.3 动态权限方案:HTTP 认证 + ACL 插件集成#

当设备数量达到数千级时,静态文件管理变得不切实际。推荐使用 mosquitto-go-auth 插件对接外部认证服务。

架构示意:

设备 → TLS → Mosquitto → auth_plugin → HTTP API → 用户数据库/ACL 服务

mosquitto.conf 配置示例:

auth_plugin /usr/lib/mosquitto-go-auth.so
# 认证后端:HTTP API
auth_opt_backends http
auth_opt_http_host http://auth.example.com
auth_opt_http_port 8080
auth_opt_http_getuser_uri /api/mqtt/user
auth_opt_http_superuser_uri /api/mqtt/superuser
auth_opt_http_aclcheck_uri /api/mqtt/acl
# 缓存(减少认证请求压力)
auth_opt_cache true
auth_opt_cache_duration 60
auth_opt_cache_type go-cache

HTTP API 需要实现三个端点:

  • GET /api/mqtt/user:验证用户密码,返回 200 表示通过
  • GET /api/mqtt/superuser:检查是否为超级用户
  • GET /api/mqtt/acl:检查 ACL 权限

自行实现时注意: 认证接口需要低延迟(< 10ms),因为每次连接和发布/订阅操作都会触发。建议在 Mosquitto 本机或同机房部署认证服务,并对结果做本地缓存。

2.1 提示: Mosquitto 2.1 采用全新的 C 插件系统替代旧版 auth_plugin 架构,mosquitto-go-auth 等基于旧插件 API 的扩展在 2.1 上无法直接使用。2.1 用户需使用内置插件接口或等待社区适配。更多信息参考 Mosquitto 2.1 迁移指南

2.1 提示补充:从 2.0 升级至 2.1 涉及多个重大变更(如 per_listener_settings 已在 2.1 中完全移除,不再可用、max_packet_size 默认值调整)。请务必参考 官方迁移指南 完成平滑升级。

6. 高可用与桥接#

6.1 Mosquitto 桥接原理#

Mosquitto Bridge 本质是将一台 Broker 作为另一台的客户端,在两个 Broker 之间同步消息。它是实现跨机房、跨网段消息同步的核心机制。

桥接不是集群——两台 Broker 各自独立,只是互相转发对方关心的消息。消息不会在集群节点间路由或负载均衡。

6.2 双节点双向桥接配置#

节点 A 配置(mosquitto.conf):

# 节点 A 连接到节点 B
connection bridge-to-b
address node-b.example.com:8883
# 使用 TLS
bridge_cafile /etc/mosquitto/certs/ca.crt
bridge_certfile /etc/mosquitto/certs/node-a.crt
bridge_keyfile /etc/mosquitto/certs/node-a.key
# 认证
remote_username bridge_user
remote_password bridge_password
# 主题映射:将本地消息同步到远端
topic devices/# both 1
# 防止消息环路
bridge_attempt_unsubscribe true
try_private true
# 断开时清理远端订阅
cleansession true
# 自动重连
start_type automatic
restart_timeout 10 30
# 桥接心跳
keepalive_interval 60

节点 B 做镜像配置(address 指向节点 A)。

topic 映射语法: topic <topic_pattern> <direction> <qos> <local_prefix> <remote_prefix>

  • directionin(仅收)、out(仅发)、both(双向)
  • local_prefix / remote_prefix:在两端添加前缀,用于避免主题名冲突

避免消息环路的关键参数:

  • try_private true:告知远端 Broker 此连接是桥接,远端会为桥接消息设置特殊标志,避免回环
  • bridge_attempt_unsubscribe true:桥接断连时,远端 Broker 自动取消该桥接持有的所有订阅

6.3 负载均衡与客户端分发#

Mosquitto 本身不支持内置负载均衡。需要在 Broker 前面加一层 TCP 代理(Nginx Stream 或 HAProxy),将客户端连接到不同的 Broker 节点。

HAProxy 配置示例:

frontend mqtt_frontend
bind *:8883 ssl crt /etc/haproxy/certs/mqtt.pem
mode tcp
default_backend mqtt_backend
backend mqtt_backend
mode tcp
balance leastconn # 按连接数最少分发
server broker1 10.0.0.1:8883 check
server broker2 10.0.0.2:8883 check

注意事项:

  • 负载均衡必须是 TCP 层(Layer 4),不能用 HTTP 层(MQTT 不是 HTTP 协议)
  • balance leastconn 适合 MQTT 长连接场景(连接数均分)
  • 分发后客户端固定连到同一后端(stick-table / persistence),避免会话状态丢失
  • 如果 Broker 间没有桥接,连到不同 Broker 的客户端互相看不到对方的消息

6.4 高可用方案局限性与替代方案#

Mosquitto 桥接的局限:

  • 桥接是异步的,存在消息延迟(通常几十毫秒到数秒)
  • 不保证分布式一致性——两台 Broker 各有一个持久化存储,数据并不总是同步
  • 不支持共享订阅:同一主题分发到不同节点上的订阅者时无法负载均衡
  • 客户端需要自行处理断线重连和重新订阅(Clean Session)
  • 没有内置故障检测和自动故障转移

替代方案:

  • EMQX Enterprise:商业版支持真正的集群,内置高可用和自动故障转移,单集群可支持百万级连接
  • VerneMQ:开源 Erlang 实现,天然支持集群,共享订阅和会话持久化
  • NanoMQ:边缘端超轻量 Broker,适合与 EMQX 配合形成边缘+云端架构

选型建议:如果设备量持续增长且高可用是硬性要求,尽早切换到集群型 Broker 比在 Mosquitto 上不断打补丁更经济。

7. 将 Mosquitto 作为系统服务运行#

7.1 Systemd 服务文件编写#

包管理器安装的 Mosquitto 通常自带 systemd 单元。自定义编译或需要调优时,可手写服务文件:

/etc/systemd/system/mosquitto.service
[Unit]
Description=Mosquitto MQTT Broker
Documentation=man:mosquitto(8)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
# 安全加固(Kubernetes 等特定环境可能需要 MOSQUITTO_UNSAFE_ALLOW_SYMLINKS 环境变量)
User=mosquitto
Group=mosquitto
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ReadWritePaths=/var/lib/mosquitto /var/log/mosquitto
ReadOnlyPaths=/etc/mosquitto/certs
# 资源限制
LimitNOFILE=100000
MemoryMax=1G
TasksMax=1024
[Install]
WantedBy=multi-user.target

关键参数说明:

  • Type=simple:Mosquitto 是前台进程,用 simple 即可(Mosquitto 2.0+ 也支持 Type=notify 配合 -d 参数,但 simple 更通用)
  • ExecReload=/bin/kill -HUP $MAINPID:发送 SIGHUP 信号,Mosquitto 会重新加载配置而不会断开现有连接
  • LimitNOFILE=100000:覆盖系统默认的文件描述符限制
  • ProtectSystem=strict:只允许写明确指定的路径

7.2 开机自启与服务管理#

Terminal window
# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 开机自启
sudo systemctl enable mosquitto
# 启动服务
sudo systemctl start mosquitto
# 查看状态
sudo systemctl status mosquitto
# 重载配置(不中断连接)
sudo systemctl reload mosquitto
# 重启服务
sudo systemctl restart mosquitto
# 查看日志
sudo journalctl -u mosquitto -f

配置变更流程(零停机):

  1. 修改 /etc/mosquitto/mosquitto.conf
  2. 执行 mosquitto -c /etc/mosquitto/mosquitto.conf --check 检查配置语法
  3. sudo systemctl reload mosquitto(SIGHUP 重载)
  4. 检查日志确认新配置生效
  5. 如果配置变更涉及 listener 端口,需要 restart 而非 reload

8. 监控、日志与运维#

8.1 日志配置与轮转#

Mosquitto 日志配置:

log_dest file /var/log/mosquitto/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information
connection_messages true
log_timestamp true
log_timestamp_format %Y-%m-%dT%H:%M:%S
  • connection_messages:记录每次客户端连接/断开事件——排查设备掉线问题必备
  • log_timestamp_format:ISO 8601 格式便于日志分析工具解析

logrotate 配置:

/etc/logrotate.d/mosquitto
/var/log/mosquitto/mosquitto.log {
daily
rotate 30
missingok
notifempty
compress
delaycompress
postrotate
/bin/kill -HUP $(cat /var/run/mosquitto/mosquitto.pid 2>/dev/null) 2>/dev/null || true
endscript
}

8.2 内置主题监控($SYS#

Mosquitto 通过 $SYS 主题层级暴露内部运行状态。需要在配置中启用:

sys_interval 60 # 每60秒更新一次 $SYS 主题

关键监控指标:

主题说明
$SYS/broker/clients/connected当前连接数
$SYS/broker/clients/maximum历史最大连接数
$SYS/broker/messages/received累计接收消息
$SYS/broker/messages/sent累计发送消息
$SYS/broker/messages/stored当前持久化存储的消息数
$SYS/broker/bytes/received累计接收字节
$SYS/broker/bytes/sent累计发送字节
$SYS/broker/heap/current当前堆内存使用量
$SYS/broker/store/messages/count持久化存储消息计数
$SYS/broker/versionBroker 版本

$SYS/broker/version 主题可用于在混合版本环境中确认各节点版本。

注意: $SYS 主题默认仅允许本地连接查看。如果远程查看,需要在 ACL 中显式放行,但这会暴露内部信息——通常不推荐。

8.3 对接外部监控#

Prometheus + mosquitto_exporter:

Terminal window
# 拉取并运行 mosquitto_exporter
docker run -d \
--name mosquitto-exporter \
-p 9234:9234 \
-e MOSQUITTO_URL=mqtt://localhost:1883 \
sapcc/mosquitto-exporter

mosquitto_exporter 作为 MQTT 客户端订阅 $SYS/# 主题,将指标转为 Prometheus 格式。配合 Grafana 仪表盘实现可视化监控。

关键告警规则:

groups:
- name: mosquitto
rules:
- alert: HighConnectionCount
expr: mosquitto_clients_connected > 50000
for: 5m
labels:
severity: warning
annotations:
summary: "Mosquitto 连接数超过 50000"
- alert: BrokerDown
expr: up{job="mosquitto"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Mosquitto Broker 宕机"

8.4 定期健康检查脚本#

/usr/local/bin/mqtt-health-check.sh
#!/bin/bash
BROKER="localhost"
PORT="8883"
TOPIC="health/check/$(hostname)"
MESSAGE="ok-$(date +%s)"
CAFILE="/etc/mosquitto/certs/ca.crt"
# 发布并订阅——验证完整的发布/订阅链路
timeout 10 mosquitto_sub \
--cafile "$CAFILE" \
-h "$BROKER" -p "$PORT" \
-t "$TOPIC" -C 1 &
SUB_PID=$!
sleep 1
timeout 5 mosquitto_pub \
--cafile "$CAFILE" \
-h "$BROKER" -p "$PORT" \
-t "$TOPIC" -m "$MESSAGE"
wait $SUB_PID 2>/dev/null
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "[OK] MQTT broker is healthy"
exit 0
else
echo "[ERROR] MQTT broker health check failed"
exit 1
fi

将脚本加入 cron 或监控调度器,每分钟执行一次。

9. 性能调优#

9.1 系统级调优#

/etc/sysctl.d/99-mosquitto.conf
# 增加 TCP 缓冲区
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 65536 8388608
# 启用 TCP Fast Open(减少 TLS 握手延迟)
net.ipv4.tcp_fastopen = 3
# 增大 backlog
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
# TIME_WAIT 优化
net.ipv4.tcp_tw_reuse = 1

应用配置:

Terminal window
sudo sysctl -p /etc/sysctl.d/99-mosquitto.conf

确保文件描述符限制已配置(见 2.1 节)。

9.2 Mosquitto 调优参数#

# 最大连接数(根据服务器能力设置,避免 OOM)
max_connections 100000
# 单次可发送的最大未确认消息数(飞行窗口)
# QoS 1/2 场景尤其重要——过低影响吞吐,过高消耗内存
max_inflight_messages 20
# 单客户端最大队列消息数(QoS 1/2 离线消息)
# 过大可能导致客户端重连时一次性推送过多消息
max_queued_messages 1000
# 最大消息体大小(默认无限制)
message_size_limit 256K
# TCP_NODELAY:禁用 Nagle 算法,降低延迟
# 对 MQTT 这种小消息频繁发送的场景提升明显
set_tcp_nodelay true

参数调优优先级(由高到低):

  1. set_tcp_nodelay true——立竿见影降低延迟
  2. max_inflight_messages——根据客户端网络质量调整。局域网可设 50-100;公网 IoT 建议 10-20
  3. max_queued_messages——内存和离线可靠性之间的权衡

9.3 持久化与 autosave 频率调优#

# 持久化保存间隔(秒)
autosave_interval 300
# 消息变更次数达到阈值时立即保存(不等 autosave_interval)
autosave_on_changes true
# 持久化时是否只保存变更(增量保存,减少 IO)
persistence true
persistence_location /var/lib/mosquitto/

权衡: autosave_interval 越短,重启后丢失的持久化消息越少,但磁盘 IO 越高。10000 设备以下的规模,300 秒是合适值。如果每条消息都至关重要(如计费数据),降低到 60 秒。

如果消息量极大且不需要 Broker 保留离线消息(客户端重连后从上游重新拉取),将 QoS 0 作为默认值可大幅降低持久化压力。

10. 测试与验证#

10.1 基本发布/订阅测试#

Terminal window
# 终端1:订阅
mosquitto_sub -h localhost -p 8883 --cafile /etc/mosquitto/certs/ca.crt -t "test/#" -v
# 终端2:发布
mosquitto_pub -h localhost -p 8883 --cafile /etc/mosquitto/certs/ca.crt -t "test/hello" -m "hello world"
# QoS 1 测试(要求确认)
mosquitto_pub -h localhost -p 8883 --cafile /etc/mosquitto/certs/ca.crt -t "test/qos1" -m "qos1" -q 1
# 保留消息测试
mosquitto_pub -h localhost -p 8883 --cafile /etc/mosquitto/certs/ca.crt -t "test/retained" -m "retained" -r
# 新开订阅窗口,应立即收到 retained 消息
mosquitto_sub -h localhost -p 8883 --cafile /etc/mosquitto/certs/ca.crt -t "test/retained" -C 1

10.2 TLS 连接测试#

Terminal window
# 单向 TLS 测试
mosquitto_sub -h mqtt.example.com -p 8883 \
--cafile /etc/ssl/certs/ca-certificates.crt \
-t "test/tls" -v
# 双向 TLS 测试(客户端提供证书)
mosquitto_sub -h mqtt.example.com -p 8883 \
--cafile /etc/mosquitto/certs/ca.crt \
--cert /etc/mosquitto/certs/client.crt \
--key /etc/mosquitto/certs/client.key \
-t "test/tls" -v
# 使用 openssl 验证证书链
openssl s_client -connect mqtt.example.com:8883 -showcerts

10.3 认证与 ACL 权限测试#

Terminal window
# 用户名密码认证测试
mosquitto_pub -h localhost -p 8883 \
--cafile /etc/mosquitto/certs/ca.crt \
-u sensor_001 -P "password123" \
-t "devices/sensor_001/telemetry/temperature" -m "25.5"
# 验证 ACL 拒绝:尝试写入无权主题(应失败)
mosquitto_pub -h localhost -p 8883 \
--cafile /etc/mosquitto/certs/ca.crt \
-u sensor_001 -P "password123" \
-t "devices/sensor_002/telemetry/temperature" -m "25.5"
# 预期:Connection Refused: not authorised
# 验证 $SYS 主题禁止访问
mosquitto_sub -h localhost -p 8883 \
--cafile /etc/mosquitto/certs/ca.crt \
-u sensor_001 -P "password123" \
-t '$SYS/broker/clients/connected'
# 预期:Connection Refused: not authorised

10.4 性能基准测试工具#

mqtt-benchmark(Go 实现,轻量推荐):

Terminal window
# 安装
go install github.com/krylovsk/mqtt-benchmark@latest
# 1000 个客户端,每个每秒发 10 条消息,持续 60 秒
mqtt-benchmark \
--broker tcp://localhost:8883 \
--count 1000 \
--size 100 \
--clients 100 \
--qos 1 \
--time 60 \
--username "bench_user" \
--password "bench_pass"

emqtt-bench(Erlang 实现,高并发基准测试):

Terminal window
# 10 万连接建立测试
emqtt_bench conn -h localhost -p 8883 -c 100000

解释关键指标:

  • 连接建立速率(conn/s):系统接受新连接的效率
  • 消息吞吐(msg/s):实际生产负载能力
  • 端到端延迟(p99):99% 的消息在多少毫秒内送达

11. 备份与灾难恢复#

11.1 需要备份的内容#

备份项路径重要性
配置文件/etc/mosquitto/mosquitto.conf高(恢复后即可启动)
密码文件/etc/mosquitto/passwd高(丢失则所有设备无法认证)
ACL 文件/etc/mosquitto/acl
TLS 证书/etc/mosquitto/certs/
桥接配置/etc/mosquitto/conf.d/中(如有桥接)
持久化数据库/var/lib/mosquitto/mosquitto.db低(离线消息丢了影响有限)

11.2 自动化备份脚本#

/usr/local/bin/mosquitto-backup.sh
#!/bin/bash
BACKUP_DIR="/backup/mosquitto/$(date +%Y%m%d_%H%M%S)"
RETENTION_DAYS=30
mkdir -p "$BACKUP_DIR"
cp -r /etc/mosquitto "$BACKUP_DIR/config"
cp /var/lib/mosquitto/mosquitto.db "$BACKUP_DIR/" 2>/dev/null || true
# 打包
tar czf "$BACKUP_DIR.tar.gz" -C "$(dirname "$BACKUP_DIR")" "$(basename "$BACKUP_DIR")"
rm -rf "$BACKUP_DIR"
# 清理 30 天前的旧备份
find /backup/mosquitto -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: $BACKUP_DIR.tar.gz"

cron 定时执行:

Terminal window
0 2 * * * /usr/local/bin/mosquitto-backup.sh >> /var/log/mosquitto-backup.log 2>&1

11.3 从备份恢复并验证#

Terminal window
# 1. 停止 Mosquitto
sudo systemctl stop mosquitto
# 2. 解压备份
BACKUP_FILE="/backup/mosquitto/20260516_020000.tar.gz"
tar xzf "$BACKUP_FILE" -C /tmp/restore
# 3. 恢复配置文件
sudo cp /tmp/restore/*/config/mosquitto.conf /etc/mosquitto/
sudo cp /tmp/restore/*/config/passwd /etc/mosquitto/
sudo cp /tmp/restore/*/config/acl /etc/mosquitto/
sudo cp /tmp/restore/*/config/certs/* /etc/mosquitto/certs/
# 4. 恢复持久化数据(可选)
sudo cp /tmp/restore/*/mosquitto.db /var/lib/mosquitto/
sudo chown mosquitto:mosquitto /var/lib/mosquitto/mosquitto.db
# 5. 检查配置
mosquitto -c /etc/mosquitto/mosquitto.conf --check
# 6. 启动并验证
sudo systemctl start mosquitto
sudo systemctl status mosquitto
mosquitto_sub -h localhost -t "test" -C 1

12. 版本升级策略#

12.1 升级前兼容性检查#

Terminal window
# 查看当前版本
mosquitto -h | head -1
# 备份(升级前必须做)
sudo systemctl stop mosquitto
sudo tar czf /backup/mosquitto-pre-upgrade-$(date +%Y%m%d).tar.gz /etc/mosquitto /var/lib/mosquitto
# 检查配置兼容性(用新版本检查旧配置)
# 下载新版本但不安装,用 --check 模式验证
/path/to/new/mosquitto -c /etc/mosquitto/mosquitto.conf --check

重点关注:Eclipse Mosquitto 发布说明 中的 Breaking Changes 部分。2.0 版本引入了大量不兼容变更(如默认仅监听 localhost、需显式配置 listener 和 allow_anonymous)。

12.2 原地升级步骤#

Terminal window
# 1. 备份(见 12.1)
# 2. 停止旧版本
sudo systemctl stop mosquitto
# 3. 升级(Ubuntu 示例)
sudo apt update
sudo apt install --only-upgrade mosquitto mosquitto-clients
# 4. 检查配置(如果包管理器提示配置冲突,选择保留旧配置,手动合并)
diff /etc/mosquitto/mosquitto.conf /etc/mosquitto/mosquitto.conf.dpkg-new
# 5. 启动新版本
sudo systemctl start mosquitto
sudo systemctl status mosquitto
journalctl -u mosquitto -n 20 --no-pager

12.3 回退方案#

Terminal window
# 降级到旧版本(已知旧版本号的情况)
sudo apt install mosquitto=2.0.18-0mosquitto1~ubuntu22.04.1
# 或从备份完全恢复
sudo systemctl stop mosquitto
tar xzf /backup/mosquitto-pre-upgrade-20260516.tar.gz -C /
sudo systemctl start mosquitto

升级后至少观察 24 小时,确认连接数、消息吞吐等指标正常,再视为升级成功。

13. 常见问题排查#

无法绑定端口 / 权限拒绝

Error: Unable to bind to port 8883

原因:端口已被占用,或非 root 用户绑定 1024 以下端口。

排查:

Terminal window
# 检查端口占用
ss -tlnp | grep 8883
# 检查 SELinux(RHEL 系列)
sudo ausearch -m avc -ts recent | grep mosquitto

解决:如果 Mosquitto 以非 root 用户运行,用 setcap 授权:

Terminal window
sudo setcap 'cap_net_bind_service=+ep' /usr/sbin/mosquitto

TLS 握手失败

OpenSSL Error: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed

常见原因:

  • 证书过期:openssl x509 -in /etc/mosquitto/certs/server.crt -noout -dates
  • 客户端未指定 CA 证书(单向认证时需 --cafile 参数)
  • 加密套件不匹配:客户端 TLS 版本过低
  • 证书中的 CN/SAN 与客户端连接的域名不匹配

ACL 限制导致订阅失败

Connection Refused: not authorised

定位方法:

Terminal window
# 查看 Mosquitto 日志
sudo grep "denied" /var/log/mosquitto/mosquitto.log
# 输出示例:1727848012: Denied PUBLISH to devices/sensor_002/data for sensor_001

根据日志中的用户名和主题调整 ACL 文件中的规则。

大量 “connection refused” — 文件描述符上限

Error: Too many open files

检查:

Terminal window
# 查看进程的 fd 限制
cat /proc/$(pidof mosquitto)/limits | grep "open files"
# 查看当前 fd 使用量
ls /proc/$(pidof mosquitto)/fd | wc -l

如超出限制,按 2.1 节和 7.1 节增大 nofile 限制。

内存异常增长

常见原因:max_queued_messages 设置过大(如 0 表示无限),大量离线客户端堆积 QoS 1/2 消息。

排查:

Terminal window
# 查看堆内存使用
mosquitto_sub -t '$SYS/broker/heap/current' -C 1
# 查看存储消息数
mosquitto_sub -t '$SYS/broker/store/messages/count' -C 1

调小 max_queued_messages(如 500-1000),确认 autosave_interval 合理。

客户端频繁重连(遗嘱消息风暴)

现象:Broker 发布大量遗嘱消息,客户端反复重连。

可能原因:

  • 客户端超时设置过短,网络波动时频繁触发遗嘱
  • Broker 处理能力不足,导致心跳超时

解决:

  • 增大客户端的 keepalive 参数(如从 30s 提升到 120s)
  • 检查 Broker 是否 CPU 或 IO 饱和——用 $SYS 主题或 top 排查

14. 附录#

14.1 生产环境完整 mosquitto.conf 模板#

# ============================================================
# Mosquitto MQTT Broker - 生产就绪配置模板
# 适用版本:2.0.x(2.1 用户请参考官方迁移指南,大部分基础配置仍兼容。注意:在 2.1.x 中,原 acl_file 和 password_file 的功能已由官方插件 mosquitto_acl_file 与 mosquitto_password_file 提供,配置方式有所变化,具体请查阅官方迁移指南。)
# ============================================================
# --- 基础参数 ---
pid_file /var/run/mosquitto/mosquitto.pid
user mosquitto
# --- 日志 ---
log_dest file /var/log/mosquitto/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information
connection_messages true
log_timestamp true
log_timestamp_format %Y-%m-%dT%H:%M:%S
# --- 持久化 ---
persistence true
persistence_location /var/lib/mosquitto/
autosave_interval 300
autosave_on_changes true
# --- 网络:仅 TLS(禁用明文) ---
# 不配置 listener 1883,强制所有客户端使用 TLS
listener 8883
protocol mqtt
# --- TLS 证书(单向认证) ---
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
cafile /etc/mosquitto/certs/ca.crt
require_certificate false
tls_version tlsv1.2
ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
# --- WebSocket(按需启用) ---
# listener 9001
# protocol websockets
# --- 认证 ---
allow_anonymous false
password_file /etc/mosquitto/passwd
# --- 权限控制 ---
acl_file /etc/mosquitto/acl
# --- 性能 ---
max_connections 100000
max_inflight_messages 20
max_queued_messages 1000
message_size_limit 256K
set_tcp_nodelay true
# --- 系统监控(仅限本地访问) ---
sys_interval 60
# --- 自定义配置目录(拆分配置文件) ---
include_dir /etc/mosquitto/conf.d

14.2 常用 mosquitto_passwd 命令速查#

Terminal window
# 创建密码文件(首次)
mosquitto_passwd -c /etc/mosquitto/passwd <username>
# 添加用户
mosquitto_passwd /etc/mosquitto/passwd <username>
# 删除用户
mosquitto_passwd -D /etc/mosquitto/passwd <username>
# 批量添加(脚本)
while IFS=: read -r user pass; do
mosquitto_passwd -b /etc/mosquitto/passwd "$user" "$pass"
done < users.txt
# 重载密码文件(不重启 Mosquitto)
sudo systemctl reload mosquitto # 或 kill -HUP $(pidof mosquitto)

14.3 ACL 文件最佳实践示例#

# ============================================================
# ACL 文件最佳实践
# ============================================================
# 规则 1:超级管理员(全局读写)
user admin
topic readwrite #
# 规则 2:后端服务(可读所有设备数据,可发控制指令)
user backend
topic read devices/+/telemetry/#
topic read devices/+/status/#
topic write devices/+/commands/#
topic readwrite health/#
# 规则 3:使用 pattern 为每个设备创建独立主题空间
# %u 自动替换为用户名
pattern read devices/%u/telemetry/#
pattern write devices/%u/telemetry/#
pattern readwrite devices/%u/config/#
# 规则 4:只读监控用户
user monitor
topic read devices/+/status/#
# 规则 5:公共主题(所有认证用户可读)
pattern read public/#
# 规则 6:全局禁止访问系统主题(放在最后)
pattern deny $SYS/#

参考资源:

Mosquitto MQTT Broker 生产就绪部署指南
https://blog.syomega.top/posts/mosquitto-mqtt-broker-guide/
作者
酱w
发布于
2026-05-16
许可协议
CC BY-NC-SA 4.0