Ubuntu 20.04下5分钟搞定Mosquitto MQTT服务器搭建(含WebSocket支持)

📅 发布时间:2026/7/3 2:18:45 👁️ 浏览次数:
Ubuntu 20.04下5分钟搞定Mosquitto MQTT服务器搭建(含WebSocket支持)
Ubuntu 20.04下5分钟搞定Mosquitto MQTT服务器搭建含WebSocket支持最近在折腾一个智能家居的Demo需要让浏览器里的前端页面直接和家里的传感器设备“对话”。传统的MQTT客户端大多是桌面应用或者命令行工具但要让网页也能实时收发消息就得让MQTT Broker支持WebSocket协议。在Ubuntu 20.04上用Mosquitto来实现这个需求其实比想象中要简单得多。这篇文章我就把自己从零开始在Ubuntu 20.04 LTS上快速部署一个支持WebSocket的Mosquitto服务器的完整过程以及一些关键的配置心得和避坑指南分享给大家。无论你是物联网开发者还是想实现浏览器端实时数据推送这套方案都能让你在几分钟内拥有一个稳定、可用的本地MQTT消息枢纽。1. 为什么选择Mosquitto与WebSocket组合在深入动手之前我们得先搞清楚两个核心问题为什么是Mosquitto以及为什么需要WebSocket支持Mosquitto是Eclipse基金会旗下的一款轻量级、开源的消息代理服务器完全实现了MQTT协议。它的优势在于资源占用少、配置相对简单、社区活跃并且是许多Linux发行版官方仓库的“常客”。对于个人开发、原型验证乃至中小型生产环境它都是一个非常可靠的选择。而WebSocket是一种在单个TCP连接上进行全双工通信的协议。对于MQTT而言其原生基于TCP但浏览器中的JavaScript无法直接创建原始的TCP连接。WebSocket协议为MQTT在浏览器中的运行提供了一个标准的“桥梁”。当Mosquitto启用了WebSocket支持后前端开发者就可以直接使用诸如MQTT.js、Paho MQTT这样的JavaScript库在网页中连接到MQTT服务器实现订阅主题和发布消息。这个组合解决了物联网和Web应用融合的一个关键痛点让数据从物理设备到云端再到用户浏览器形成一条无缝、低延迟的实时数据流。想象一下你不再需要为每个数据展示都写一个后端API接口去轮询设备数据通过MQTT发布网页直接订阅数据变化立即可见。2. 系统准备与Mosquitto安装我们的战场是Ubuntu 20.04 LTS。确保你的系统已经更新到最新状态这是一个好习惯。sudo apt update sudo apt upgrade -y接下来安装Mosquitto。在Ubuntu 20.04上我们可以直接使用官方APT仓库这比从源码编译要省心得多。默认仓库里的版本可能不是最新的但对于绝大多数功能需求来说已经足够稳定。sudo apt install mosquitto mosquitto-clients -y这条命令做了两件事mosquitto: 安装了MQTT代理服务器本身。mosquitto-clients: 安装了用于测试的客户端工具包包含mosquitto_pub发布和mosquitto_sub订阅两个非常实用的命令行工具。安装完成后系统会自动启动mosquitto服务并设置为开机自启。我们可以通过以下命令验证服务是否正常运行sudo systemctl status mosquitto如果看到Active: active (running)的字样并且没有报错那么恭喜你一个最基本的MQTT服务器已经在1883端口MQTT默认端口上运行起来了。此时你可以进行一个最简单的本地回环测试打开一个终端订阅一个测试主题比如test/topicmosquitto_sub -h localhost -t test/topic打开另一个终端向同一个主题发布一条消息mosquitto_pub -h localhost -t test/topic -m Hello from Ubuntu 20.04!如果第一个终端窗口立刻显示了Hello from Ubuntu 20.04!那么基础MQTT服务就完全正常了。但这还不够我们的目标是支持WebSocket。3. 启用与配置WebSocket支持默认安装的Mosquitto并不包含WebSocket支持。我们需要安装一个额外的插件并修改配置文件。首先安装Mosquitto的WebSocket插件包sudo apt install libwebsockets-dev mosquitto-dev -y注意libwebsockets-dev是WebSocket的C语言库开发文件mosquitto-dev则包含了编译Mosquitto插件所需的头文件。接着安装动态安全模块和WebSocket支持插件。在Ubuntu 20.04的仓库中这些通常是独立的包sudo apt install mosquitto-dynamic-security mosquitto-websockets -y安装完成后关键的步骤来了——配置。Mosquitto的主配置文件位于/etc/mosquitto/mosquitto.conf。Ubuntu的包管理器通常会为我们生成一个默认配置。我们需要编辑它添加WebSocket监听器。建议先备份原始配置sudo cp /etc/mosquitto/mosquitto.conf /etc/mosquitto/mosquitto.conf.backup然后使用你喜欢的编辑器如nano或vim打开配置文件sudo nano /etc/mosquitto/mosquitto.conf在配置文件的末尾或者找一个合适的位置比如在已有的listener 1883附近添加以下配置# 标准MQTT over TCP监听端口 (默认) listener 1883 allow_anonymous true # WebSocket监听端口 listener 8083 protocol websockets allow_anonymous true让我解释一下这几行配置的含义listener 1883: 这行可能已经存在它定义了MQTT over TCP的监听端口。保持它让传统的MQTT客户端如设备、手机App可以继续连接。listener 8083: 我们新增一个监听器端口号为8083你可以选择其他未被占用的端口如9001也常用。protocol websockets:这是关键指令它告诉Mosquitto这个监听器使用WebSocket协议来处理连接。allow_anonymous true: 为了测试方便我们暂时允许匿名连接。在生产环境中这必须被关闭并配置严格的认证我们会在下一节详细讨论。一个更清晰的两者对比配置示例如下监听器类型端口协议用途典型客户端TCP 监听器1883原生 MQTT over TCP物联网设备、移动应用、桌面客户端Arduino, Node-RED, Python PahoWebSocket 监听器8083MQTT over WebSocket网页浏览器、Node.js应用JavaScript (MQTT.js), Web前端保存并退出编辑器。然后重启Mosquitto服务以使配置生效sudo systemctl restart mosquitto再次检查服务状态确保重启没有出错sudo systemctl status mosquitto4. 安全加固与身份验证一个允许匿名访问且暴露在网络的MQTT服务器是极其危险的。任何人都有可能连接到你的服务器发布垃圾信息甚至恶意指令。因此安全配置不是可选项而是必选项。我们将从匿名访问控制和密码认证两个方面进行加固。首先关闭匿名访问。编辑/etc/mosquitto/mosquitto.conf找到或添加以下行确保其值为falseallow_anonymous false这意味着任何客户端连接时都必须提供用户名和密码。接下来我们需要创建密码文件并添加用户。创建密码文件Mosquitto提供了一个工具mosquitto_passwd来管理密码文件。sudo touch /etc/mosquitto/passwd sudo mosquitto_passwd -U /etc/mosquitto/passwd第一条命令创建了一个空密码文件第二条命令-U参数会创建一个包含初始哈希值的文件。或者你也可以在添加第一个用户时自动创建文件。添加用户使用mosquitto_passwd命令添加用户。这里以添加用户web_client为例sudo mosquitto_passwd /etc/mosquitto/passwd web_client执行后命令行会提示你输入并确认该用户的密码。在配置文件中指定密码文件在mosquitto.conf中添加或修改以下行password_file /etc/mosquitto/passwd配置访问控制列表ACL - 可选但推荐仅凭密码还不够精细。ACL允许你控制哪个用户可以订阅或发布哪些主题。创建一个ACL文件sudo nano /etc/mosquitto/aclfile添加内容例如# 用户 web_client 可以订阅以 “sensor/” 开头的任何主题但只能发布到 “control/web” 主题 user web_client topic read sensor/# topic write control/web然后在mosquitto.conf中指定ACL文件acl_file /etc/mosquitto/aclfile完成以上配置后你的mosquitto.conf中关于安全和WebSocket的核心部分应该类似这样listener 1883 allow_anonymous false password_file /etc/mosquitto/passwd acl_file /etc/mosquitto/aclfile listener 8083 protocol websockets allow_anonymous false password_file /etc/mosquitto/passwd acl_file /etc/mosquitto/aclfile重要提示每次修改配置文件或密码/ACL文件后都需要重启Mosquitto服务sudo systemctl restart mosquitto。现在无论是通过1883端口的TCP连接还是通过8083端口的WebSocket连接客户端都必须提供有效的用户名和密码才能通信并且其操作权限受到ACL规则的限制。5. 实战测试从命令行到浏览器配置完成后我们必须进行全面测试确保TCP和WebSocket两种连接方式都工作正常且安全规则生效。测试1TCP连接测试使用mosquitto_clients由于我们关闭了匿名访问之前的测试命令需要加上用户名和密码参数。假设我们创建的用户是testuser密码是testpass。终端1订阅mosquitto_sub -h localhost -t sensor/temperature -u testuser -P testpass -v-v参数会打印出主题和消息方便查看。终端2发布mosquitto_pub -h localhost -t sensor/temperature -u testuser -P testpass -m 22.5如果终端1成功收到sensor/temperature 22.5说明TCP连接及密码认证成功。测试2WebSocket连接测试使用Node.js脚本这是重头戏。我们将用一个简单的Node.js脚本模拟浏览器环境进行测试。首先确保安装了Node.js和mqtt库。npm install mqtt -g # 全局安装或者在你的项目目录内 npm install mqtt创建一个名为test_ws.js的文件const mqtt require(mqtt); // 注意连接地址的协议是 ws:// (非加密) 或 wss:// (加密) // 端口是我们配置的 8083 const client mqtt.connect(ws://localhost:8083, { username: testuser, password: testpass, clientId: test_web_client_ Math.random().toString(16).substr(2, 8) }); client.on(connect, function () { console.log(✅ 已通过WebSocket连接到MQTT服务器); // 订阅主题 client.subscribe(sensor/#, function (err) { if (!err) { console.log(✅ 已订阅主题 sensor/#); // 发布一条测试消息 client.publish(sensor/humidity, 65%); } }); }); client.on(message, function (topic, message) { // 收到消息 console.log( 收到消息 [${topic}]: ${message.toString()}); }); client.on(error, function (error) { console.error(❌ 连接错误:, error); });运行这个脚本node test_ws.js如果看到✅ 已通过WebSocket连接到MQTT服务器和✅ 已订阅主题 sensor/#的输出并且脚本没有退出说明WebSocket连接成功。此时你可以在另一个终端用mosquitto_pub向sensor/humidity发布消息看这个Node.js脚本是否能收到。测试3真正的浏览器测试创建一个简单的index.html文件引入MQTT.js的浏览器版本可以从CDN获取!DOCTYPE html html head titleMQTT over WebSocket 测试/title script srchttps://unpkg.com/mqtt/dist/mqtt.min.js/script /head body h2浏览器MQTT客户端/h2 button onclickconnect()连接/button button onclickpublish()发布测试消息/button div idmessages/div script let client null; const host ws://你的服务器IP:8083; // 将你的服务器IP替换为实际地址 const options { username: testuser, password: testpass, clientId: browser_client_ Math.random().toString(16).substr(2, 8) }; function connect() { client mqtt.connect(host, options); client.on(connect, () { log(✅ 已连接到服务器); client.subscribe(sensor/#, (err) { if (!err) log(✅ 已订阅 sensor/#); }); }); client.on(message, (topic, message) { log( 收到 [${topic}]: ${message.toString()}); }); client.on(error, (err) { log(❌ 错误: ${err}); }); } function publish() { if (client client.connected) { client.publish(control/web, Hello from Browser!); log( 已发布消息到 control/web); } else { log(⚠️ 请先连接); } } function log(msg) { const div document.getElementById(messages); div.innerHTML p${new Date().toLocaleTimeString()}: ${msg}/p; } /script /body /html将这个HTML文件放在一个Web服务器如Nginx、Apache或简单的Python HTTP服务器下然后在浏览器中打开。点击“连接”按钮如果配置正确你应该能看到成功的连接和订阅日志。点击“发布测试消息”消息会通过WebSocket发送到Mosquitto服务器。6. 性能调优与生产环境考量一个能“跑起来”的服务器和一個能“扛得住”的服务器是两回事。当你准备将这套方案用于开发测试后期或小型生产环境时以下几个方面的调优至关重要。连接数限制与资源管理默认配置可能不适合高并发。在mosquitto.conf中可以调整# 最大同时连接数根据服务器内存调整 max_connections -1 # -1表示无限制生产环境建议设置一个数值如1000 # 每个客户端允许的最大待处理消息数飞行窗口 max_inflight_messages 20 # 消息队列的最大长度 max_queued_messages 1000 # 是否持久化客户端会话断线重连后恢复订阅 persistence true persistence_location /var/lib/mosquitto/日志与监控清晰的日志有助于排查问题。Mosquitto支持多种日志级别和输出方式。# 将日志输出到标准错误和系统日志 log_dest stderr log_dest syslog # 日志级别error, warning, notice, information, debug, subscribe, unsubscribe, websockets log_type all # 如果你只想看错误和连接信息可以更精确控制 log_type error log_type connection对于监控可以订阅Mosquitto自动发布的$SYS/#系统主题获取服务器状态、连接数、消息统计等信息。这是一个非常强大的内置监控功能。使用SSL/TLS加密通信WSS我们测试用的是ws://明文WebSocket这在公网是极不安全的。生产环境必须启用wss://基于SSL/TLS的WebSocket。这需要你拥有一个域名和对应的SSL证书可以从Let‘s Encrypt免费获取。配置如下# TCP MQTT with SSL listener 8883 cafile /etc/ssl/certs/ca-certificates.crt certfile /etc/mosquitto/certs/server.crt keyfile /etc/mosquitto/certs/server.key allow_anonymous false # WebSocket with SSL (WSS) listener 8084 protocol websockets cafile /etc/ssl/certs/ca-certificates.crt certfile /etc/mosquitto/certs/server.crt keyfile /etc/mosquitto/certs/server.key allow_anonymous false配置SSL后前端连接地址需改为wss://你的域名:8084。防火墙配置确保服务器的防火墙如ufw只开放必要的端口sudo ufw allow 22/tcp # SSH sudo ufw allow 1883/tcp # MQTT (如果对外) sudo ufw allow 8083/tcp # WebSocket (如果对外且未加密) sudo ufw allow 8084/tcp # WebSocket over SSL/TLS (推荐对外) sudo ufw enable7. 常见问题与故障排除在搭建和使用的过程中你可能会遇到一些问题。这里列出几个我踩过的坑和解决方法。1. 服务启动失败提示 “Address already in use”这意味着你配置的端口如1883, 8083已被其他程序占用。使用sudo netstat -tlnp | grep :端口号查看是哪个进程占用了端口并停止它或为Mosquitto更换端口。2. WebSocket连接失败出现网络错误或连接被拒绝检查配置确认mosquitto.conf中listener和protocol websockets的配置正确无误且端口号一致。检查服务状态运行sudo systemctl status mosquitto查看是否有关于WebSocket加载的错误日志。常见错误是mosquitto-websockets插件未正确安装。可以尝试重新安装sudo apt install --reinstall mosquitto-websockets。检查防火墙确保服务器防火墙和云服务商的安全组规则允许了WebSocket端口如8083的入站连接。3. 客户端能连接但收不到消息检查ACL规则这是最常见的原因。确认你的测试用户在有订阅read权限的主题上。可以暂时在ACL文件中添加一行topic read #给予该用户读取所有主题的权限进行测试。检查主题匹配MQTT主题是大小写敏感的。确保发布和订阅的主题字符串完全一致。检查QoS级别发布和订阅时的QoS级别不匹配可能导致消息丢失。在测试阶段可以都使用QoS 0。4. 如何查看详细的运行日志修改mosquitto.conf将日志级别设置为debug并输出到文件或控制台log_dest file /var/log/mosquitto/mosquitto.log log_type debug然后重启服务并复现问题查看日志文件/var/log/mosquitto/mosquitto.log中的详细输出。注意调试完毕后应将日志级别调回error或warning以免日志文件过大。5. 如何彻底卸载Mosquitto如果你想从头再来sudo systemctl stop mosquitto sudo systemctl disable mosquitto sudo apt purge mosquitto mosquitto-clients mosquitto-websockets -y sudo rm -rf /etc/mosquitto/ /var/lib/mosquitto/ /var/log/mosquitto/执行完这些命令后Mosquitto及其配置文件、数据、日志都会被清除。