4. Mosquitto Broker 部署与配置
这一章我们聊聊 Mosquitto Broker 的实战部署。说实话,我在很多物联网项目里都离不开它——轻量、稳定、社区活跃。但真正把它用好,光会 apt install 可不够。源码交叉编译、配置文件调优、自启动服务、性能摸底,这些才是生产环境的关键。
本章核心脉络:从交叉编译开始,到配置详解,再到服务化与性能测试,一条线走通 Mosquitto 的嵌入式部署全流程。
4.1 源码交叉编译:从 PC 到嵌入式板卡
为什么非要源码交叉编译?我遇到过不少朋友直接在开发板上 apt install mosquitto,结果发现版本太老,或者缺少某些功能(比如 TLS 支持)。嵌入式环境里,交叉编译是基本功。
先准备好交叉编译工具链。以 ARM Cortex-A7 为例:
# 设置环境变量
export CC=arm-linux-gnueabihf-gcc
export CXX=arm-linux-gnueabihf-g++
export AR=arm-linux-gnueabihf-ar
export RANLIB=arm-linux-gnueabihf-ranlib
# 下载 Mosquitto 源码
wget https://mosquitto.org/files/source/mosquitto-2.0.18.tar.gz
tar xzf mosquitto-2.0.18.tar.gz
cd mosquitto-2.0.18
然后配置编译选项。我个人习惯把依赖库都静态链接进去,避免目标板上缺库:
# 配置编译选项
make CC=${CC} CXX=${CXX} \
CFLAGS="-I/path/to/openssl/include -I/path/to/cjson/include" \
LDFLAGS="-L/path/to/openssl/lib -L/path/to/cjson/lib" \
WITH_TLS=yes \
WITH_SRV=no \
WITH_WEBSOCKETS=yes \
WITH_CJSON=yes \
prefix=/usr/local/mosquitto
make install DESTDIR=/path/to/target/rootfs
我的经验:WITH_WEBSOCKETS 这个选项,如果你的网关需要支持 Web 端 MQTT 连接(比如浏览器直接订阅),一定要打开。我有个项目就是忘了开这个,后来返工重编,浪费时间。
编译完成后,检查一下生成的文件:
# 查看编译产物
file /path/to/target/rootfs/usr/local/mosquitto/sbin/mosquitto
# 输出示例:ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked
嗯,确认是 ARM 架构的可执行文件,这一步就对了。
4.2 配置文件详解:监听端口、认证与 ACL
Mosquitto 的配置文件默认在 /etc/mosquitto/mosquitto.conf。说实话,默认配置只能用于开发测试,生产环境必须自己手写。
4.2.1 监听端口配置
最基本的配置就是监听端口。你可以监听多个端口,每个端口绑定不同的协议:
# 标准 MQTT 端口
listener 1883
# 加密 MQTT 端口(TLS)
listener 8883
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate false
# WebSocket 端口
listener 8083
protocol websockets
我曾经在项目里踩过一个坑:同时开了 1883 和 8883,但忘了给 8883 配证书,结果客户端连不上。排查了半天才发现是证书路径写错了。
4.2.2 认证配置
认证方式有三种:匿名、密码文件、外部认证。生产环境我强烈建议用密码文件:
# 关闭匿名访问
allow_anonymous false
# 指定密码文件
password_file /etc/mosquitto/passwd
# 创建用户(在目标板上执行)
mosquitto_passwd -c /etc/mosquitto/passwd admin
# 然后输入密码,比如:Admin123!
密码文件是加密存储的,直接 cat 看不到明文。但要注意,mosquitto_passwd 工具必须在目标板上运行,或者用交叉编译版本。
注意:密码文件权限要设置为 600,否则 Mosquitto 会拒绝启动。我见过有人把 passwd 文件设成 777,结果 broker 直接报错退出。
4.2.3 ACL 访问控制
ACL(Access Control List)用来控制每个用户能发布和订阅哪些主题。没有 ACL,任何用户都能往任何主题发消息,那不乱套了?
# 启用 ACL
acl_file /etc/mosquitto/acl
# 示例 ACL 文件内容
# 用户 admin 有所有权限
user admin
topic readwrite #
# 用户 sensor1 只能发布到 sensors/ 下
user sensor1
topic write sensors/#
# 用户 app1 只能订阅 alerts/ 下
user app1
topic read alerts/#
# 匿名用户只能读取 public/ 下
topic read public/#
ACL 的匹配规则是从上到下,第一条匹配就生效。所以要把精确的规则写在前面,宽泛的写在后面。
| 配置项 | 作用 | 生产建议 |
|---|---|---|
allow_anonymous |
是否允许匿名连接 | false(关闭) |
password_file |
用户密码文件路径 | 权限 600,放在 /etc/mosquitto/ |
acl_file |
访问控制列表路径 | 按最小权限原则设计 |
listener |
监听端口与协议 | 1883+8883 双端口 |
4.3 Mosquitto 作为系统服务自启动
嵌入式设备经常断电重启,Mosquitto 必须能自动启动。我一般用 systemd,但如果你的板子比较老(比如 Busybox 环境),那就用 init.d 脚本。
4.3.1 systemd 方式(推荐)
创建服务单元文件 /etc/systemd/system/mosquitto.service:
[Unit]
Description=Mosquitto MQTT Broker
After=network.target
Wants=network.target
[Service]
Type=simple
ExecStart=/usr/local/mosquitto/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
User=mosquitto
Group=mosquitto
[Install]
WantedBy=multi-user.target
然后启用并启动:
systemctl daemon-reload
systemctl enable mosquitto
systemctl start mosquitto
systemctl status mosquitto
小技巧:RestartSec=5 的意思是如果崩溃了,等 5 秒再重启。我遇到过因为网络延迟导致启动失败的情况,这个参数能避免频繁重启。
4.3.2 init.d 方式(老系统)
如果你的板子没有 systemd,那就用传统的 init.d 脚本:
#!/bin/sh
# /etc/init.d/mosquitto
case "$1" in
start)
echo "Starting Mosquitto..."
/usr/local/mosquitto/sbin/mosquitto -d -c /etc/mosquitto/mosquitto.conf
;;
stop)
echo "Stopping Mosquitto..."
killall mosquitto
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
然后设置开机启动:
chmod +x /etc/init.d/mosquitto
update-rc.d mosquitto defaults
4.4 Broker 性能测试:用数据说话
配置好了,跑起来了,但性能怎么样?别猜,测一下。我习惯用 Mosquitto 自带的 mosquitto_sub 和 mosquitto_pub 做基础测试。
4.4.1 基础连通性测试
# 终端1:订阅主题
mosquitto_sub -h 192.168.1.100 -p 1883 -t "test/topic" -u admin -P "Admin123!"
# 终端2:发布消息
mosquitto_pub -h 192.168.1.100 -p 1883 -t "test/topic" -m "Hello, MQTT!" -u admin -P "Admin123!"
如果终端1收到了 "Hello, MQTT!",说明基本功能正常。
4.4.2 吞吐量测试
用 mosquitto_pub 的 -n 参数可以指定消息数量,配合 -r 看速率:
# 发布 10000 条消息,每条 100 字节
mosquitto_pub -h 192.168.1.100 -t "perf/test" \
-n 10000 -l -u admin -P "Admin123!" \
-m "$(python3 -c 'print("A"*100)')"
我一般会记录三个指标:
| 指标 | 说明 | 参考值(ARM Cortex-A7) |
|---|---|---|
| 消息吞吐量 | 每秒能处理多少条消息 | 5000-15000 msg/s |
| 延迟(P99) | 99% 的消息延迟上限 | < 10ms |
| 并发连接数 | 同时连接的客户端数量 | 500-2000 |
注意:性能数据受硬件、网络、消息大小影响很大。上面是我在某个项目上的实测值,你的环境可能不同。一定要在自己板子上跑一遍。
4.4.3 压力测试工具
如果要做更专业的压力测试,我推荐用 mqtt-benchmark 或者 emqtt_bench。不过对于嵌入式环境,自带的工具已经够用了。
# 用 bash 脚本模拟多客户端
for i in {1..100}; do
mosquitto_sub -h 192.168.1.100 -t "sensor/$i/data" -u "user$i" -P "pass$i" &
done
# 然后观察 CPU 和内存占用
top -b -n 1 | grep mosquitto
嗯,到这里,Mosquitto 的部署与配置就基本成型了。从交叉编译到配置调优,再到服务自启动和性能摸底,每一步都有讲究。记住一句话:生产环境不要偷懒,该编译的编译,该配置的配置,该测试的测试。