
做工业数据采集或者搞IOT项目迟早要跟MQTT打交道。我最早是在树莓派上折腾Mosquitto轻量确实轻量但设备一多、要管理账号、要看消息流转、要接规则引擎的时候它就有点力不从心了。后来换到EMQX才算真正把“服务器”的感觉做出来。这篇文章就完整记录我在Ubuntu 20.04上从零搭建EMQX的整个过程包括方案选型、环境优化、安装配置、账号密码管理、发布订阅测试以及怎么跟485设备这种工业现场对接。适合刚接触MQTT的新手也适合已经用着Mosquitto、准备换更完整方案的朋友。MQTT协议本身不复杂就是发布/订阅模型但真正落地的时候坑全在细节里端口开没开、认证怎么配、ACL怎么设、客户端怎么连、消息怎么订阅……这篇我尽量用大白话把每一步讲透你照着敲命令基本能跑通。1. 为什么选Ubuntu 20.04 EMQX先把方案想清楚1.1 Ubuntu 20.04还值不值得用总有朋友问现在都出到22.04、24.04了怎么还用20.04如果你用的是云服务器或者工控机很多商业镜像、边缘网关出厂自带的系统就是20.04不是你想升就能升。而且20.04是LTS版本支持周期到2025年官方源还在持续维护部署老项目、对接厂家SDK的时候反而少踩很多坑。就拿我自己的例子来说手头有一台工控机出厂就是Ubuntu 20.04上面还跑了采集程序不到万不得已我不会去动系统版本。EMQX官方对20.04的支持也很好apt源、deb包都有对应版本装起来比源码编译省太多事。所以别纠结“系统是不是太老”能用、能维护、能跑稳就是好系统。1.2 从Mosquitto换到EMQX的真实理由Mosquitto最大的优点是轻几十MB内存就能跑。但当你需要以下能力的时候它就有点吃力了多用户、多设备的账号体系和权限控制不够直观没有可视化界面排查问题全靠命令行和日志消息保留、离线消息、数据桥接这些功能要么没有要么配置繁琐集群能力弱单机挂了就全挂EMQX是开源MQTT Broker用Erlang/OTP写的并发能力强一台机器扛几万连接不稀奇。它自带一个Web控制台能看到谁连着、哪些主题在流转、消息速率多少。还内置了认证、ACL、数据持久化甚至可以通过规则引擎把消息转发到MySQL、Kafka。做正经项目我建议直接上EMQX。对比项MosquittoEMQX资源占用极低中等但可控Web管理界面无有功能完整账号权限管理配置较繁琐Dashboard可视化操作规则引擎/数据桥接弱强支持多种外部系统大规模并发一般强工业协议接入需自己开发配合Neuron等组件1.3 EMQX版本选型4.x还是5.x现在官方主力是5.x版本4.x已经进入维护期。5.x在配置体系、API、认证方式上做了很多调整如果你是全新部署直接上5.x没错。网上很多教程还在讲4.x的emqx_auth_mnesia、etc/plugins那套5.x完全不是这么回事我在文章后面的“常见问题与排查”里会专门说这个坑。我这次安装用的是EMQX 5.x版本安装方式选择官方apt源或者下载deb包二选一。如果你以后要升级、要管理多个实例用apt源会更方便。2. 环境准备装系统、关休眠、换国内源2.1 系统基础检查拿到一台Ubuntu 20.04服务器或虚拟机先做三件事# 1. 检查系统版本 lsb_release -a # 2. 检查内存和磁盘 free -h df -h # 3. 更新系统索引 sudo apt updateEMQX对硬件要求并不高单机测试1核1G就够跑生产环境建议2核4G起步。磁盘主要用来放日志和数据默认安装完大概占用几百MB日志会随运行时间增长建议日志目录所在分区留出至少10G空间后面我会说怎么看日志、怎么控制日志大小。2.2 服务器千万别休眠这里有个特别容易忽略的问题如果你用的是Ubuntu桌面版或者带图形界面的工控机系统默认可能开了休眠和挂起功能。服务器跑着跑着屏幕黑了、服务断了查了半天发现是系统自己睡过去了。直接屏蔽掉sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target执行完再确认一下systemctl status sleep.target显示masked就说明已经被禁用了。这一步不做EMQX装得再好系统一休眠什么服务都白搭。我见过不止一个朋友在虚拟机里折腾半天连不上最后发现是VMware的客户机系统自己挂了。2.3 换国内源省下大量等待时间Ubuntu自带源在国外国内服务器执行apt update或者安装依赖包时速度不稳定。我习惯把源换成国内的镜像站这里以清华源为例# 备份原有源列表 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak # 编辑源列表 sudo vim /etc/apt/sources.list把内容替换为deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse然后执行sudo apt update2.4 防火墙与端口规划Ubuntu 20.04默认可能开着ufw防火墙。EMQX装完以后客户端要连1883端口浏览器要访问18083控制台这两件事如果被防火墙挡住外部设备根本连不上。先看防火墙状态sudo ufw status如果是active状态放行必要端口sudo ufw allow 1883/tcp sudo ufw allow 8083/tcp sudo ufw allow 8084/tcp sudo ufw allow 18083/tcp这里顺便把几个常用端口列清楚端口用途1883MQTT over TCP主要设备接入端口8883MQTT over SSL/TLS加密连接8083MQTT over WebSocket浏览器调试用8084MQTT over WSSWebSocket加密18083Dashboard管理控制台注意如果你用的是云服务器光改服务器内部的ufw还不够安全组或防火墙规则里也必须放行这些端口。新手最容易在这里卡住——服务明明跑着外面就是连不上。3. EMQX安装与基础配置3.1 安装方式对比EMQX在Ubuntu 20.04上有两种主流安装方式官方apt源安装适合以后用apt install emqx方便升级下载deb包手动安装适合离线部署或者指定版本号我更推荐apt源的方式因为EMQX更新频率不算低用apt管理最省心。手动下载deb包适合网速不理想、或者内网环境没法连外网的情况。3.2 使用官方apt源安装官方提供了一键安装脚本本质是先配置apt源再安装curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash这个脚本会自动帮你添加EMQX的软件源并执行安装。如果你不想用一键脚本也可以手动配置源然后sudo apt update sudo apt install emqx安装完成后EMQX会注册成systemd服务直接启动sudo systemctl start emqx sudo systemctl enable emqx查看运行状态sudo systemctl status emqx看到active (running)就说明服务已经起来了。再用自带的CLI工具确认一下emqx ctl status输出类似Node emqx127.0.0.1 is started基本就装好了。3.3 手动下载deb包安装离线服务器或者特殊版本需求走这条路。到EMQX官网下载页面找到对应Ubuntu 20.04的deb包然后用sudo dpkg -i emqx-5.x.x-ubuntu20.04-amd64.deb如果提示缺少依赖执行sudo apt -f install自动把缺的依赖补上。3.4 配置文件与关键目录EMQX 5.x安装完成后几个关键位置你得心里有数路径作用/etc/emqx/emqx.conf主配置文件/etc/emqx/certs/证书目录/var/lib/emqx/数据目录/var/log/emqx/运行日志目录主配置文件里最常用的是listeners.tcp.default和dashboard.listeners.http两个段。默认1883和18083端口都在监听一般不需要改。只有遇到端口冲突的时候才需要动。查看当前监听端口ss -lntp | grep -E 1883|18083|8083能看到LISTEN状态就说明没问题。3.5 初始化Dashboard管理员浏览器访问http://你的服务器IP:18083第一次打开会让你创建管理员账号密码。这里创建的是Dashboard的登录账号跟后面设备连接MQTT用的账号是两套体系别搞混。登录进去以后主界面能看到当前连接数、订阅数、消息速率这些指标。这个控制台是EMQX最值钱的地方之一排障基本靠它。我建议登录后第一时间去“系统设置”里把管理员密码改掉并且不要用弱密码。4. 给EMQX添加账号密码认证与授权4.1 为什么要给设备单独建账号默认配置下EMQX是允许匿名连接的也就是说任何客户端只要知道IP和端口就能直接连上来发布订阅消息。这在小范围测试时挺方便但一旦设备联网或者跟外部系统对接这种行为等于把消息通道暴露在公网上。我个人的习惯是从第一天就关掉匿名认证全部设备用独立账号连接。这样出问题的时候能查到是哪台设备在发消息也能按设备粒度做权限控制。4.2 关闭匿名认证在Dashboard里点击“访问控制”菜单找到“认证”选择一个认证方式。最简单的是内置数据库认证。EMQX 5.x里配置认证的路径是Dashboard - 访问控制 - 认证 - 创建认证 - 选择“内置数据库”。创建完成后进入该认证的配置页面把“启用认证”打开此时匿名连接就会被拒绝。如果没找到这个开关也可以在主配置文件里面加一行authentication [ { mechanism password_based, backend built_in_database, enable true } ]改完配置后重启服务sudo systemctl restart emqx4.3 在Dashboard里添加MQTT用户认证开启以后回到Dashboard在“访问控制” - “认证” - “内置数据库”里点“添加用户”填入用户名和密码。这里的用户名密码是给MQTT客户端连1883端口用的。我建议用户名和设备编号挂钩比如device_001、gateway_02方便后续排查。密码尽量随机生成不要用123456这种。添加完成后用客户端连接时就需要携带这个账号密码否则会被拒绝连接。注意Dashboard登录账号和MQTT设备账号是两个概念。Dashboard是给你看的MQTT账号是给设备用的。别在代码里拿着Dashboard密码去连接连不上。4.4 基于主题的权限控制ACL认证只管“能不能连上来”ACL管的是“连上来之后能干什么”。生产环境里我不希望每台设备都能订阅所有主题更不希望它随便往别人的主题里发消息。在Dashboard - 访问控制 - 授权里可以配置规则例如客户端device_001只允许发布/订阅device/001/#主题客户端device_001禁止订阅device/002/#允许gateway_01向data/gateway/01/#发布消息这个做法的价值在安全也在整洁。设备之间互相不能串消息日志里也更容易追踪。4.5 用TLS加密传输进阶如果设备要走公网连接明文1883端口传数据等于裸奔。有条件的话建议启用TLS把证书放到/etc/emqx/certs/然后在Dashboard里启用8883端口监听选择证书文件即可。这个配置本身不复杂难点在于证书从哪来。自签名证书适合测试正式环境建议用正规CA签发的证书或者用ACME自动签发。这块够单独写一篇这里先提个方向个人项目至少知道有这回事。5. 发布订阅实测从命令行到Python代码5.1 用mosquitto客户端快速验证EMQX装好、账号配好别急着写代码先用命令行工具验证一下通路。安装客户端工具sudo apt install mosquitto-clients终端A订阅主题mosquitto_sub -h 127.0.0.1 -p 1883 -u device_001 -P 你的密码 -t device/001/data -v终端B发布消息mosquitto_pub -h 127.0.0.1 -p 1883 -u device_001 -P 你的密码 -t device/001/data -m hello from ubuntu如果终端A打印出了那行消息说明从认证到主题路由全链路通了。这里用127.0.0.1测试可以排除防火墙干扰如果本机都连不通先查账号密码和服务状态如果本机通、其他机器不通再去查防火墙和安全组。5.2 MQTTX图形化调试利器命令行适合快速验证但做复杂调试我还是推荐MQTTX这个工具跨平台支持TCP、WebSocket、SSL多种连接方式。在MQTTX里填好连接地址、端口、用户名密码点连接就能看到所有收发消息界面里还能设置QoS、保留消息标记。MQTTX特别适合排查“消息到底发没发出去”这类问题——对比一下订阅端有没有收到就知道问题是出在发布端、Broker还是订阅端。5.3 MQTT关键概念QoS、保留消息、会话这里有必要把几个高频概念说透因为80%的调试问题都出在这几个地方。QoS级别有三种0表示最多一次发出去就不管了可能丢1表示至少一次会重传直到收到确认可能重复2表示恰好一次最严格但开销最大。我平时的经验是普通温湿度、状态量用QoS 0就够了控制指令用QoS 1保证送达QoS 2很少用除非对重复极其敏感。保留消息Retained Message的作用是发布时把retain置1Broker会保存这条消息的“最新值”新订阅者一订阅就能立刻收到而不是必须等下一次发布。做设备状态展示的时候特别好用比如设备上线与否这个状态发布一次保留住后面任何人订阅都能立即看到。Clean Session决定客户端断开时Broker是否帮你缓存离线消息。如果订阅端断线重连很重要就把clean_session设为false这样离线期间的消息会在重连后补发。但要注意缓存是占内存的别对大量主题都这么做。5.4 用Python写一个发布订阅Demo命令行验证完下一步就是用代码接入毕竟实际项目里不会是手动敲命令。安装paho-mqttpip install paho-mqtt订阅端代码import paho.mqtt.client as mqtt BROKER 你的服务器IP PORT 1883 USERNAME device_001 PASSWORD 你的密码 TOPIC device/001/data def on_connect(client, userdata, flags, rc): if rc 0: print(连接成功) client.subscribe(TOPIC, qos1) else: print(f连接失败返回码{rc}) def on_message(client, userdata, msg): print(f收到主题: {msg.topic}) print(f内容: {msg.payload.decode()}) client mqtt.Client() client.username_pw_set(USERNAME, PASSWORD) client.on_connect on_connect client.on_message on_message client.connect(BROKER, PORT, keepalive60) client.loop_forever()发布端代码import paho.mqtt.client as mqtt BROKER 你的服务器IP PORT 1883 USERNAME device_001 PASSWORD 你的密码 TOPIC device/001/control client mqtt.Client() client.username_pw_set(USERNAME, PASSWORD) client.connect(BROKER, PORT, keepalive60) payload {relay: 1, action: on} result client.publish(TOPIC, payload, qos1) if result.rc 0: print(消息发布成功) else: print(消息发布失败) client.disconnect()paho-mqtt的on_connect回调里rc返回0才表示成功。如果返回4或者5基本都是认证问题——账号不对、密码不对或者服务端没开这个认证方式。返回1一般是协议版本问题检查一下有没有设protocolmqtt.MQTTv311。6. 485设备接入把Modbus转成MQTT6.1 现场为什么需要“桥”很多工控现场的老设备都是RS485接口走Modbus RTU协议跟TCP/IP完全不搭。要把这些设备的数据送进MQTT服务器中间必须有一层“翻译”。这里涉及到热搜词里那个“mqtt如何给485设备发指令读取数据”的问题。简单说就是双向的上行方向要读设备寄存器里的数据打包成JSON发到MQTT主题下行方向要订阅某个控制主题收到指令后转成Modbus写寄存器命令通过串口发给485设备。6.2 方案A串口服务器硬件直转市面上很多串口服务器RS485转以太网支持MQTT功能配置一下就能实现双向透传。这类设备本质上是把串口数据塞进MQTT的payload里代价是数据结构不标准要看厂家协议。便宜、部署快但灵活性一般。适合简单需求比如一个485设备对应一个主题payload直接用十六进制字符串。6.3 方案B边缘网关加NeuronEMQX官方有一个工业协议网关组件叫Neuron专门干Modbus、OPC UA这类协议到MQTT的转换。它可以在边缘网关或者服务器上跑跟EMQX配合得很顺毕竟是自家产品。Neuron里配置好串口参数、设备地址、寄存器和MQTT主题的映射关系以后采集到的数据会自动发布到EMQX。要下发指令也简单Neuron会订阅你指定的主题收到JSON后解析并执行Modbus写入。这块值得单独写教程这里先说明思路Neuron 协议翻译官 数据采集器EMQX 消息中枢两者配合能省掉大量自研驱动的工作。6.4 方案CPython自己写串口采集如果你只有一两台设备又不愿意添硬件从头写一个简单的采集脚本也完全可行。思路是用pyserial打开RS485串口拼装Modbus RTU帧读保持寄存器解析返回的数据用paho-mqtt发布到device/001/data主题核心代码片段import serial import struct import paho.mqtt.client as mqtt ser serial.Serial(/dev/ttyUSB0, 9600, timeout1) def modbus_read_holding(slave_id, register, length): # 构建Modbus RTU请求帧 cmd struct.pack(B B H H, slave_id, 0x03, register, length) crc modbus_crc(cmd) ser.write(cmd crc) # 读取响应并解析 resp ser.read(7 2 * length) return resp # CRC校验函数略 # 读取到数据后组织成JSON通过paho发布真正落地的时候要注意几点串口参数对应好波特率和校验位485是半双工所以收发包之间要留间隔读寄存器的地址范围跟设备说明书核对好。这套方案最考验排查能力但也是最能学到东西的路径。7. 常见问题与排查技巧实录7.1 服务起不来端口被占用EMQX启动失败最典型的原因就是端口冲突。1883被别的程序占了或者之前装过另一个MQTT服务忘记卸载。排查命令sudo ss -lntp | grep 1883看到占用程序的PID后根据情况选择停掉相关服务或者修改EMQX监听端口。我遇到过一次是测试用的Mosquitto没关两个Broker抢同一端口停掉就好了。7.2 客户端连上了但一订阅就断线这个现象挺迷惑。连都连上了一订阅就被踢。大概率不是认证问题而是ACL规则把订阅动作拒绝了。去Dashboard的“授权”配置里看看有没有把当前用户对应的主题放行。我之前设过一个规则只允许发布、没允许订阅结果订阅端一执行subscribe就被断开在日志里找authorization相关记录才定位到。7.3 本机能连、外网连不上八成是防火墙或云安全组的问题。本机用127.0.0.1测试能通说明服务本身没问题。外部连不上先把ufw status看一遍再把云控制台的安全组入站规则检查一遍。很多朋友只改了后台安全组忘了服务器内部ufw或者反过来。调试的时候可以直接sudo ufw status verbose看详细规则再配合tcpdump -i eth0 port 1883抓包看请求有没有到网卡一步步缩小范围。7.4 日志里全是connect error但账号明明没错如果日志反复出现客户端连接失败的记录但用户名密码看着没问题优先检查EMQX版本。EMQX 5.x的密码校验默认用的是password_based算法跟4.x的默认行为不一样。如果你是从4.x迁移过来的用户列表生成的密码哈希可能对不上。建议在Migration场景下重新在5.x里创建用户或者通过Dashboard重新设置密码确保哈希算法一致后再测试连接。现象排查命令/位置常见原因服务启动失败ss -lntp端口被占用客户端连接被拒Dashboard认证配置匿名认证未开/账号密码错订阅即断线日志搜authorizationACL规则未放行外网连不上ufw status、安全组防火墙阻挡日志提示连接错误/var/log/emqx/emqx.log认证配置不匹配7.5 一个来自血的教训升级前先备份配置EMQX从4.x升到5.x配置格式变化很大。我有一台老服务器升级后起不来排查半天发现是旧配置文件里的插件配置和新版本不兼容。后来恢复备份老老实实重新在5.x里配了一遍。所以我的建议是sudo cp -r /etc/emqx /etc/emqx.bak.$(date %Y%m%d)升级前一定做这个动作。别图省事真要出问题的时候这个备份能救命。8. 写在最后的几点体会这套环境我前前后后搭过多次从最初照着教程一步步敲到现在能在几分钟内部署完中间踩过的坑基本都写在上面了。要说最想提醒新朋友的事情就三点第一服务器一定要关休眠第二1899端口和防火墙的套路要弄清楚第三账号密码和ACL在项目一开始就规范好别等设备多了再补。另外EMQX官方文档其实很完善遇到问题别急着搜博客先去查文档对应版本的内容。网上很多教程写的还是老版本照着做反而踩坑。如果只是想本地快速验证用Docker跑一个emqx/emqx镜像也行但做生产环境我更喜欢直接装在系统里少一层容器依赖排查问题也直观。后面有机会我再写一篇EMQX规则引擎接MySQL实现消息持久化的教程那是另一个很有意思的话题。先到这里希望对正在折腾MQTT服务器的你有帮助。