手把手带你搭建 MQTT服务(EMQX)

发布时间:2026/9/6 22:40:17
手把手带你搭建 MQTT服务(EMQX) 前言欢迎来到xxxzsh 的 MQTT 三部曲。这是一个围绕 MQTT 的系列文章我会用三篇内容带你完整走一遍 MQTT 在真实项目中的使用过程——从理解协议到搭建服务再到 Java 项目接入。在上一篇里我们已经把 MQTT 的基本概念、设计思路以及它适合解决什么问题讲清楚了。这一篇我们直接进入实战搭建一个 MQTT Broker本篇会以EMQX作为示例带大家完成MQTT 服务的启动管理控制台的使用客户端连接与账号配置基础的权限隔离思路本文不会再重复 MQTT 的基础原理因此更适合已经对 MQTT 有基本了解的同学阅读。如果你想先系统了解 MQTT可以先阅读第一篇MQTT 是什么一文读懂 MQTT 协议的原理与优势点击跳转一、MQTT ≠ 服务学习了MQTT原理的小伙伴应该明白但由于这个概念非常重要所以我还是要重申一下。在实际使用中我们需要部署一个实现了 MQTT 协议的消息服务器Broker客户端才能通过 MQTT 协议进行通信。常见的 MQTT Broker 实现包括 Mosquitto、HiveMQ、EMQX 等。本文选择EMQX作为 MQTT Broker并通过 Docker 的方式进行部署。后文中提到的“MQTT 服务”均指 EMQX 提供的 MQTT Broker 能力而非 MQTT 协议本身。下面开始运行EMQX二、Docker运行EMQX创建挂载目录mkdir -p /opt/emqx/{data,log,etc} chmod -R 777 /opt/emqxdocker 启动docker run -d \ --name emqx \ --restart unless-stopped \ -p 1883:1883 \ -p 8883:8883 \ -p 8083:8083 \ -p 8084:8084 \ -p 18083:18083 \ -v /opt/emqx/data:/opt/emqx/data \ -v /opt/emqx/log:/opt/emqx/log \ emqx/emqx:5.8.8docker-compose 启动emqx:image: emqx:5.8.8container_name: emqxrestart: unless-stoppedenvironment:- EMQX_NODE__NAMEemqx127.0.0.1 # 固定节点名称ports:- 1883:1883 # MQTT TCP- 8883:8883 # MQTT SSL- 8083:8083 # MQTT over WebSocket- 8084:8084 # MQTT over WSS- 18083:18083 # EMQX Dashboardvolumes:- /opt/emqx/data:/opt/emqx/data- /opt/emqx/log:/opt/emqx/log端口说明端口作用1883MQTT TCP重点8883MQTT SSL8083MQTT over WS8084MQTT over WSS18083管理后台重点最主要的就是这个1883了未来最基本的TCP连接就是用这个1883。看看日志docker logs -f emqx这样就是OK了。三、使用EMQX管理控制台浏览器访问你的IP:18083账号密码默认是 admin \ public第一次登录后要改密记得保存。后续我们就要通过这个控制台去配置EMQX的客户端连接、ACL等。四、使用 MQTT 客户端工具验证 EMQX 服务前面我们已经通过 Docker 成功部署了EMQXMQTT Broker。接下来在正式开发客户端之前通常需要先验证 Broker 是否能够正常连接和收发消息。类似于MySQL 常用 NavicatRedis 常用 Redis Desktop ManagerRDM4.1 常见的 MQTT 客户端工具目前常用的 MQTT 客户端工具包括MQTTXMQTT Explorermosquitto_pub / mosquitto_sub命令行感觉各有各的好处吧。本文以MQTTX为例进行演示。官网地址MQTTX全功能 MQTT 客户端工具https://mqttx.app/zh你可以用在线的也可以下载个桌面版。MQTTX和EMQX是一家公司做的所以你会发现整体UI风格很像4.2 客户端工具连接打开MQTTX新建连接Client ID 得是全局唯一的。账号密码不用填因为现在是默认开放状态。尝试一下连接并复制一个连接连接之后我们可以新建一个监听然后我们现在来模拟一下收发。开两个窗口到这里就是OK了。你已经成功搭建好了EMQXMQTT Broker。如果是基本的学习等现在我们已经可以开始用了。比如接入你的Java项目、大数据平台等等。五、客户端认证上面我们已经搭建好了 EMQX但实际使用中我们肯定是配置访问账号密码不可能公网暴漏出去给别人随便访问。我们现在就来创建一下账号密码。EMQX提供了非常方便的创建认证方式打开管理控制台。5.1 创建数据源左侧 访问控制 - 客户端认证 - 点击右上角的创建。可以看到它有很多选择内置数据库、MySQL、MongoDB等常用数据源都可以。我们就用内置数据库就好参数配置默认。注意一旦启用了认证方式EMQX 会默认拒绝所有匿名连接只有通过认证的客户端才允许建立连接。所以如果你的MQTT正在被一些项目使用请注意项目情况。这个时候你再去客户端工具连接你就发现连不上了5.2 新建用户我创建了一个账号test密码testtest的用户打开连接工具输入账号密码就发现可以连接了六、客户端授权权限隔离在上一节中我们已经通过客户端认证实现了「只有知道账号密码的客户端才能连接 EMQX」。但在生产中这还远远不够。6.1 为什么需要客户端授权ACL我们先举一个非常典型的业务场景系统中有很多设备每个设备都有自己的 Topicdevice/{deviceId}/updevice/{deviceId}/down不同客户端的权限应该不同普通用户只能操作自己的设备管理端可以查看所有设备第三方系统只读不能发指令如果没有权限隔离会发生什么任意客户端都能订阅所有设备数据向任意设备下发指令一旦账号泄露后果不可控因此客户端授权ACL是 MQTT 系统中非常核心的一环。6.2 什么是 ACLAccess Control ListACL全称Access Control List访问控制列表。在 MQTT 中ACL 本质上解决的是一个问题谁客户端能不能对某个 Topic进行发布publish或订阅subscribe可以简单理解为一个三元组Client Action Topic其中Client客户端身份username / clientId 等Actionpublish发布subscribe订阅TopicMQTT 的主题路径6.3 ACL 规则基本语法不需要记EMQX 中File 的一条 ACL 规则的基本格式如下allow | deny who action topic拆解说明部分含义allow / deny允许 / 拒绝whousername / clientid / allactionpublish / subscribe / pubsubtopic具体的 Topic支持通配符打开 EMQX 控制台打开左侧 访问控制 - 客户端授权 可以看到默认的时候就能看到EMQX已经配置了一个File了打开可以看到按上面的语法依次解释就是允许 EMQX 管理后台dashboard 用户订阅系统监控 Topic来自本机的客户端对所有 Topic 可随便收、随便发禁止任何客户端通过通配符一次性订阅整个 MQTT 系统如果前面都没匹配到那就默认允许一切行为看到3这个就是我们不能订阅 # 来监听全部topic的原因我们注释掉更新再去连接就会发现可以订阅 # 了。再举几个简单的例子允许所有客户端订阅所有设备的上报 Topicallow all subscribe device//up禁止任何客户端向任何 Topic 发布消息deny all publish #6.4 EMQX 内置数据库配置ACL和客户端认证一样除了文件我们还可以配置其它数据源。同样打开 EMQX 控制台中的客户端授权点击右上角的创建​​本文后续的演示中我们还是使用内置数据库如下注意多个数据源存在的话它就是匹配多个规则哪个能匹配上就哪个。比如说全局的File里面我们配了禁止 # 订阅全部在内置数据源里面配置了 zhangsan 这个号可以订阅 #那么zhangsan也可以订阅成功 # 。6.5 示例场景下面我们通过一个非常贴近真实业务的例子来演示 ACL 的配置方式。假设我们有两个用户用户一张三username zhangsan只允许向自己设备S001上报数据接收自己设备的消息不能访问任何其它设备设备 Topic 设计如下device/S001/updevice/S001/down内置数据库的配置就方便的多了EMQX已经给我们封装好了。如下就是配置了zhangsan这个用户的用户二李四username lisi只允许接收所有设备的上报数据不允许向任何 Topic 发布消息6.6 在 EMQX 里ACL 能做到什么程度限制 publish / subscribe✅精确 Topic✅通配符 / #✅基于 username✅基于 clientId✅基于 IP✅动态规则✅数据库 / HTTP / JWT✅它支持动态占位符。比如 ${username} clientId之类的。6.7 优化Topic设计从上面的 6.5 我们了解到了每个用户都可以配置自己的ACL但这时你会发现这样一个个device/设备ID/up(down)之类的配置过去非常麻烦总不能以后加一个设备来编辑一次吧。所以我们可以试着优化一下MQTT的Topic的设计。首先我们明确一下需求1除了用户自己用户名下的topic其它topic都不能发布和订阅2配置完后续不需要任何的改动第一点我们直接配置一个所有用户拒绝 # 就好了。第二点我们则需要设计一下。我给两个方案方案一我们可以把设备上报的Topic改成device/所属用户/up举个例子zhangsan的两台设备S001和S002原先是上报到device/S001/updevice/S002/up那么我们都统一到device/zhangsan/up然后在上报的数据中去定义比如{id: S001,status: active...}这样后续不管来多少设备都是往用户的固定的topic发就不需要每次来都配置ACL了。这样我们的EMQX中就可以配置一个全局规则所有用户device/${username}/up需要注意的是拒绝 # 一定是要在最底下不然连接会直接被拒绝。方案二其实也类似也是先用username包一层只不过后面跟着设备ID区分。还是以zhangsan的两台设备S001和S002的两台为例device/zhangsan/S001/updevice/zhangsan/S002/up...然后在所有用户配置中就可以用device/${username}/#或者device/${username}//up设计起来反正都大差不差。我这里就抛砖引玉一下大家在实战中摸索两次就懂了。七、总结本文中我们完成了从EMQX 环境搭建到生产级权限管控的全过程快速部署利用 Docker 的便捷性我们几分钟内就搭建起了一个高性能的 MQTT Broker。安全加固通过“客户端认证”确保只有合法用户能进入系统。精细化管理通过“ACL 授权”我们实现了业务上的权限隔离彻底解决了设备间数据误发、越权监听的安全隐患。架构优化在最后的 Topic 设计优化中我们看到了如何利用动态占位符实现“一劳永逸”的权限规则配置。其实关键就在于对安全和规范的把控。MQTT 协议虽然简洁但配合 EMQX 强大的认证授权机制才能真正支撑起海量设备的安全通信。希望这篇文章能帮你打通 MQTT 学习思路。