目录

MQTT 代理自建指南:Mosquitto 配置与优化

搞物联网开发的朋友肯定绕不开 MQTT 这个协议。今天我们来聊聊怎么自建一个靠谱的 MQTT 代理服务器,用 Eclipse Mosquitto 这个开源方案。

为什么要自建?公共 MQTT 服务器虽然方便,但数据安全没保障,连接稳定性也看人家心情。自己搭建的话,数据完全掌控,还能根据需求定制优化。

需要准备什么?

物品 型号/规格 价格
服务器 树莓派 4B / 云服务器 ¥350-500
旧笔记本/台式机 ¥0 (利旧)
存储 16GB SD 卡 / SSD ¥30-200
网络 有线网络优先 ¥0
域名 可选 (用于外网访问) ¥50/年
总计 ¥80-750

我用的是家里闲置的树莓派 4B,24 小时开机功耗也就 5W 左右,一年电费不到 30 块钱,香!

步骤 1:安装 Mosquitto

Ubuntu/Debian 系统

# 更新软件源
sudo apt-get update

# 安装 Mosquitto 和客户端工具
sudo apt-get install -y mosquitto mosquitto-clients

# 查看服务状态
systemctl status mosquitto

Fedora/CentOS 系统

# 启用 EPEL 源
sudo dnf install -y epel-release

# 安装 Mosquitto
sudo dnf install -y mosquitto mosquitto-clients

# 启动服务
sudo systemctl enable mosquitto
sudo systemctl start mosquitto

Docker 方式 (推荐)

如果你已经熟悉 Docker,这种方式最干净:

docker run -d \
  --name mosquitto \
  --restart always \
  -p 1883:1883 \
  -p 9001:9001 \
  -v /opt/mosquitto/config:/mosquitto/config \
  -v /opt/mosquitto/data:/mosquitto/data \
  -v /opt/mosquitto/log:/mosquitto/log \
  eclipse-mosquitto:latest

注意事项: ⚠️ 默认安装后 Mosquitto 是允许匿名连接的,生产环境一定要配置认证!

步骤 2:基础配置

配置文件位置:/etc/mosquitto/mosquitto.conf

最小安全配置

# 备份原配置
sudo cp /etc/mosquitto/mosquitto.conf /etc/mosquitto/mosquitto.conf.bak

# 创建配置文件
sudo nano /etc/mosquitto/mosquitto.conf

填入以下内容:

# 监听端口
listener 1883
listener 9001
protocol websockets

# 禁止匿名连接
allow_anonymous false

# 密码文件路径
password_file /etc/mosquitto/passwd

# 持久化设置
persistence true
persistence_location /var/lib/mosquitto/

# 日志配置
log_dest file /var/log/mosquitto/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information

# 连接限制
max_connections 1000
max_queued_messages 100

创建用户密码

# 创建密码文件 (第一个用户用 -c 参数)
sudo mosquitto_passwd -c /etc/mosquitto/passwd admin

# 添加更多用户 (不用 -c)
sudo mosquitto_passwd /etc/mosquitto/passwd device001
sudo mosquitto_passwd /etc/mosquitto/passwd device002

# 设置文件权限
sudo chmod 600 /etc/mosquitto/passwd
sudo chown mosquitto:mosquitto /etc/mosquitto/passwd

原理解析: Mosquitto 使用 PBKDF2-SHA256 算法哈希密码,安全性足够。每个设备建议用独立账号,方便权限管理和问题排查。

步骤 3:配置 TLS 加密 (可选但推荐)

如果设备在外网访问,强烈建议上 TLS 加密。

使用 Let’s Encrypt 免费证书

# 安装 Certbot
sudo apt-get install -y certbot

# 获取证书 (需要域名)
sudo certbot certonly --standalone -d mqtt.yourdomain.com

# 证书位置
# /etc/letsencrypt/live/mqtt.yourdomain.com/fullchain.pem
# /etc/letsencrypt/live/mqtt.yourdomain.com/privkey.pem

修改 Mosquitto 配置

# TLS 监听端口
listener 8883
protocol mqtt

# 证书配置
cafile /etc/letsencrypt/live/mqtt.yourdomain.com/chain.pem
certfile /etc/letsencrypt/live/mqtt.yourdomain.com/fullchain.pem
keyfile /etc/letsencrypt/live/mqtt.yourdomain.com/privkey.pem

# 强制 TLS
require_certificate false

重启服务:

sudo systemctl restart mosquitto

步骤 4:测试连接

命令行测试

# 终端 1:订阅主题
mosquitto_sub -h localhost -p 1883 -u admin -P yourpassword -t "test/topic" -v

# 终端 2:发布消息
mosquitto_pub -h localhost -p 1883 -u admin -P yourpassword -t "test/topic" -m "Hello MQTT!"

如果看到终端 1 收到消息,说明配置成功!

Python 客户端测试

import paho.mqtt.client as mqtt
import time

# 回调函数
def on_connect(client, userdata, flags, rc):
    print(f"Connected with result code {rc}")
    client.subscribe("test/topic")

def on_message(client, userdata, msg):
    print(f"{msg.topic}: {msg.payload.decode()}")

# 创建客户端
client = mqtt.Client()
client.username_pw_set("admin", "yourpassword")
client.on_connect = on_connect
client.on_message = on_message

# 连接
client.connect("localhost", 1883, 60)
client.loop_start()

# 发布消息
for i in range(5):
    client.publish("test/topic", f"Message {i}")
    time.sleep(1)

time.sleep(3)
client.loop_stop()
client.disconnect()

步骤 5:性能优化

调整系统限制

# 编辑系统限制
sudo nano /etc/security/limits.conf

# 添加以下内容
mosquitto soft nofile 65536
mosquitto hard nofile 65536

Mosquitto 高级配置

# 消息队列优化
max_queued_messages 10000
max_inflight_messages 20
retry_interval 20

# 心跳间隔 (秒)
keepalive_interval 60

# 自动过期 (秒)
autosave_interval 1800

# 客户端超时
timeout_idle 0

监控连接状态

# 查看活跃客户端数
mosquitto_sub -t '$SYS/broker/clients/connected' -h localhost

# 查看消息统计
mosquitto_sub -t '$SYS/broker/messages/#' -h localhost

# 查看负载情况
mosquitto_sub -t '$SYS/broker/load/#' -h localhost

常见问题排查

问题 1:连接被拒绝 (Connection refused)

  • 原因: 防火墙阻止 1883 端口
  • 解决:
    sudo ufw allow 1883/tcp
    sudo ufw allow 8883/tcp
    sudo systemctl restart mosquitto

问题 2:认证失败 (Not authorized)

  • 原因: 用户名密码错误或密码文件权限不对
  • 解决:

    # 检查密码文件权限
    ls -la /etc/mosquitto/passwd
    # 应该是 -rw------- mosquitto mosquitto
    
    # 重置密码
    sudo mosquitto_passwd /etc/mosquitto/passwd admin

问题 3:TLS 连接失败

  • 原因: 证书路径错误或权限问题
  • 解决:

    # 检查证书文件
    ls -la /etc/letsencrypt/live/yourdomain/
    
    # Mosquitto 需要读取权限
    sudo chmod 644 /etc/letsencrypt/live/yourdomain/*.pem
    sudo chown mosquitto:mosquitto /etc/letsencrypt/live/yourdomain/*.pem

问题 4:消息丢失

  • 原因: QoS 级别设置不当或客户端异常断开
  • 解决:
    • 关键消息使用 QoS 1 或 QoS 2
    • 启用持久化 (persistence true)
    • 客户端设置 clean_session=false

问题 5:连接数过多导致性能下降

  • 原因: 默认配置不适合高并发
  • 解决:
    • 调整 max_connections
    • 增加系统文件描述符限制
    • 考虑集群部署 (多个 Mosquitto 实例)

总结

自建 MQTT 代理服务器其实不难,Mosquitto 这个方案轻量又稳定。关键点是:

  1. 安全第一:一定要配置认证,外网访问必须上 TLS
  2. 权限隔离:不同设备用不同账号,方便管理
  3. 监控到位:善用 $SYS 主题监控运行状态
  4. 持久化:重要数据开启 persistence 防止丢失

如果是小规模 IoT 项目,单台 Mosquitto 足够支撑几千个设备。规模再大的话,可以考虑 EMQX 这种企业级方案,或者 Mosquitto 集群部署。

希望这篇博客文章对您有所帮助!


相关资源:

更多关于 的文章
关注创客出手公众号

关注创客出手