接手一个物联网项目,第一步往往是搭消息中间件。手上正好有一台Ubuntu 20.04的服务器,需要跑MQTT服务,我选了EMQX。这篇博客就把从零开始到跑通的完整记录放出来,包括关休眠、换国内源、装EMQX、配账号密码、订阅发布实测,以及排查坑位,按步骤可复现,适合刚接触物联网消息服务的读者。
1. 方案选型与部署架构
1.1 为什么是EMQX而不是Mosquitto
物联网场景下的消息中转,很多人的第一反应是Mosquitto,轻量、单机部署快,学起来一小时就够。但一旦接入的设备量上来,需要集群、规则引擎、数据桥接,Mosquitto就得自己拼一堆插件。我这次选EMQX,核心原因是它把物联网常用的能力全做进了内核:
- 多协议接入:不止MQTT,还支持MQTT-SN、CoAP、LwM2M,后续如果接非MQTT设备不用再换中间件。
- 内置规则引擎:可以从消息里提取字段,直接转发到InfluxDB、MySQL、Kafka,省去写转发服务的成本。
- 集群原生:节点之间自动发现,水平扩展非常平滑。
- Dashboard可视化:连接数、消息速率、订阅关系一目了然,排障效率比纯命令高得多。
从资源占用来看,EMQX的Erlang/OTP虚拟机确实比Mosquitto吃内存,空闲时约150MB左右,但在2核4G的机器上跑几十台设备完全没压力。如果你只是在校验车上调几个传感器,那Mosquitto足够了;如果想做一个长期运营的物联网平台底座,直接上EMQX,省得后面迁移。
1.2 MQTT协议的三个关键角色
在动手安装前,必须把MQTT的基本模型搞清楚。MQTT里永远有三个角色:
| 角色 | 作用 | 类比 |
|---|---|---|
| Broker | 消息中转中心,就是EMQX | 邮局 |
| Publisher | 发送消息的客户端 | 寄信人 |
| Subscriber | 订阅并接收消息的客户端 | 收信人 |
三者通过**主题(Topic)**联系起来。比如温湿度传感器发布一条消息到sensor/room1/temp,监控大屏订阅了这个主题,就能实时收到数据。MQTT的订阅支持通配符,sensor/+/temp匹配所有房间的温度,#匹配多层级所有主题,这是MQTT最灵活的地方。
还有两个关键机制:QoS(服务质量)和遗嘱消息(Last Will)。QoS 0最快但可能丢消息,QoS 1至少一次但可能重复,QoS 2恰好一次但性能最差。我在实际项目里默认用QoS 1,其次是QoS 0。遗嘱消息则是设备断线时由Broker替它广播一条“我挂了”的消息,这是做设备在线监控的利器,后面配置账号时会提怎么验证。
1.3 版本选择与资源规划
这一版选EMQX很关键。目前官方提供的版本主要有4.x和5.x两条线:
- EMQX 4.x:经典版,文档丰富,网上教程多,插件机制熟悉,很多老项目还在用。
- EMQX 5.x:当前主力,Dashboard改版大,配置支持HOCON格式,Dashboard操作更顺手,资源占用优化明显。
新项目建议直接上5.x,我这里用的是5.8的社区版(Open Source版)。社区版足够支持生产级单机部署,只有集群管理、热配置等企业功能被限制,个人学习和小规模商用没问题。
资源规划方面,在Ubuntu 20.04上跑EMQX最低配1核1G也能启动,但建议至少2核2G,磁盘留10GB以上用于日志和消息堆积。我测试机是2核4G,实测连接200个客户端、每秒500条消息时CPU占用约20%,内存约500MB,完全扛得住。
2. 环境准备与Ubuntu基础调优
2.1 关闭休眠功能避免部署中断
这是Ubuntu 20.04服务器部署最容易踩的坑。默认桌面版Ubuntu会挂起系统,服务器长时间SSH操作后突然断连,多半是休眠触发了。
Ubuntu 20.04使用的是systemd管理电源状态,先检查当前休眠配置:
systemctl status sleep.target suspend.target hibernate.target hybrid-sleep.target如果状态不是inactive,直接禁用:
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.targetmask和disable的区别要理解一下。disable只是取消开机启动,系统仍然可以通过其他方式触发休眠;mask则是彻底屏蔽,连手动执行的入口都堵死。服务器场景必须用mask。
另外还要检查桌面环境自带的电源管理设置,GNOME桌面的设置在“设置”-“电源”里把“自动挂起”改为“从不”。如果用的是最小化服务器版没有桌面,只需上面的systemctl命令就够了。
还有一个细节:禁用休眠后,建议同时修改SSH断连保护参数,防止临时掉线导致安装中断。编辑/etc/ssh/sshd_config,找到ClientAliveInterval和ClientAliveCountMax,改为:
ClientAliveInterval 60 ClientAliveCountMax 3这样SSH每60秒发一次心跳包,允许连续3次超时,180秒内网络抖动不会断开连接。
2.2 换用国内源加速安装更新
Ubuntu 20.04官方源在国内有时速度感人,安装依赖可能要等几分钟。这里直接把软件源替换为阿里云镜像。先备份原配置:
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后编辑/etc/apt/sources.list:
sudo sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list sudo sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list如果之前用的是清华源之类,想统一替换也更简单,直接清空文件写入:
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse写完后刷新索引:
sudo apt update sudo apt upgrade -y顺手装上后续排查会用到的工具:
sudo apt install -y net-tools curl wget nano mosquitto-clientsmosquitto-clients这一步很多人会忽略。它自带mosquitto_pub和mosquitto_sub命令行工具,测试MQTT消息发布订阅非常方便,不用专门开IDE写测试代码。
2.3 防火墙与端口放行
EMQX默认占用下面几个端口,部署前要规划好防火墙策略:
| 端口 | 用途 |
|---|---|
| 1883 | MQTT TCP协议端口 |
| 8883 | MQTT TLS/SSL加密端口 |
| 8083 | WebSocket端口,浏览器场景用 |
| 8084 | WSS加密WebSocket端口 |
| 18083 | Dashboard管理控制台端口 |
| 4370 | 集群节点间通信端口 |
如果启用了ufw防火墙,需要放行这些端口。只放行生产必要的端口:
sudo ufw allow 1883/tcp sudo ufw allow 18083/tcp sudo ufw allow 8083/tcp sudo ufw status注意:如果是云服务器,光改系统防火墙还不够,必须同步在云控制台的安全组里放行端口。我遇到过本地ufw全开放了,但外网死活连不上的情况,最后发现是云安全组默认只放行22端口,这个问题很多新手会忽略。
测试期间如果图省事可以临时关闭防火墙,但生产环境务必保持开启,并且只放行必要端口。
3. EMQX安装与基础配置
3.1 通过APT仓库安装
官方提供两种安装方式:APT仓库和Docker。先讲APT方式,这是最推荐的生产部署方式,配置管理、日志、systemd服务都走标准路径。
EMQX提供了专门的APT仓库,安装时先导入仓库信息:
# 安装基础工具 sudo apt update sudo apt install -y curl gnupg apt-transport-https # 添加EMQX官方GPG密钥 curl -fsSL https://packages.emqx.net/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/emqx.gpg # 添加APT源 echo "deb [signed-by=/usr/share/keyrings/emqx.gpg] https://packages.emqx.net/emqx-ce/deb/ubuntu focal main" | sudo tee /etc/apt/sources.list.d/emqx.list # 刷新源并安装 sudo apt update sudo apt install -y emqx关于codename有个细节:EMQX的APT源对20.04用focal,18.04用bionic,22.04用jammy,别写错,不然后面依赖解析会出问题。
启动服务并设置开机自启:
sudo systemctl start emqx sudo systemctl enable emqx systemctl status emqx看到active (running)就说明安装成功。安装完后,默认Dashboard地址是http://你的服务器IP:18083,默认管理员账号密码是admin/public,首次登录会强制要求修改密码。
再验证一下MQTT端口是否在监听:
sudo netstat -tlnp | grep 1883 tcp6 0 0 :::1883 :::* LISTEN 12345/beam.smp看到1883端口监听就对了。这里的进程名是beam.smp,EMQX底层Erlang虚拟机的进程名,看到这个不用慌。
3.2 Docker方式对比参考
如果你的服务器上已经跑了不少Docker容器,用Docker部署EMQX也不差,对隔离环境尤其方便:
# 拉取并启动容器 docker run -d --name emqx \ -p 1883:1883 \ -p 8083:8083 \ -p 18083:18083 \ -e EMQX_DASHBOARD__DEFAULT_PASSWORD=你的密码 \ emqx/emqx:5.8Docker方式的限制主要在配置持久化上。容器内/opt/emqx/data是数据目录,必须挂载到宿主机:
docker run -d --name emqx \ -p 1883:1883 -p 8083:8083 -p 18083:18083 \ -v emqx-data:/opt/emqx/data \ -v emqx-log:/opt/emqx/log \ emqx/emqx:5.8否则容器一删配置全丢。这个坑我踩过,升级EMQX版本后直接照搬老容器配置没挂数据卷,所有用户、规则引擎、认证设置全部重置,教训极其惨痛。
个人还是更喜欢APT方式,因为升级用apt upgrade emqx就行,配置路径固定,排查文档也好对。Docker适合快速体验和多套环境隔离,生产环境建议二选一后保持统一。
3.3 Dashboard初始化与基本设置
通过浏览器访问http://IP:18083,第一次登录会看到初始化界面。这里要做的核心事情就一件:改掉默认管理员密码。
登录后进入 Dashboard,每个版本的界面可能有差异,但设置逻辑一致:
- 左侧菜单找“管理”-“用户管理”,修改
admin用户的密码。 - 确认版本号与节点状态正常,默认只有一个节点,状态为Running。
- 检查系统内存和连接数指标,确认无异常报警。
Dashboard右上角能看到当前连接数、订阅数、消息流入流出速率,这四个数字是判断服务是否健康的第一抓手。心跳正常但消息收发为0,大概率是订阅主题不匹配;消息流入有数值但流出为0,一般是订阅端没有连上来。这种监控视角比看日志快得多。
提示:如果18083端口无法访问,先本地curl试一下:
curl -I http://127.0.0.1:18083。本机能通外网不通,查防火墙和安全组;本机都不通,查emqx服务状态和端口监听。
4. 账号密码与访问控制配置
4.1 内建认证添加用户
EMQX刚装好时MQTT客户端可以匿名连接,生产环境必须关掉。我选择用内置数据库认证(Built-in Database),不需要额外依赖,配置简单。
在Dashboard左侧菜单进入“访问控制”->“认证”,点击“创建”按钮:
- 认证方式:选择“密码认证”(Password-Based)
- 后端类型:选择“内置数据库”(Built-in Database)
- 数据源:默认选中“内置数据库”即可
- 保存后全局认证即启用
然后在“访问控制”-“用户管理”里“添加用户”,填入客户端ID和密码。这里有个常见误区:EMQX的用户名(Username)和MQTT的Client ID是两个概念。Username是认证凭据,Client ID是连接标识,两者可以相同,也可以不同。规则引擎处理时,通常两侧都能拿到。
我实际项目中习惯按设备类型规划用户名,比如device_temp_001、gateway_485_01,密码生成随机串并写入设备端配置。注意,EMQX的密码不支持明文直接入库,5.x版本会自动使用BCrypt算法做哈希,创建用户时只需要填明文密码,系统自动加盐处理。
配置完成后,需要再确认“认证”页面里的状态是启用。另外每添加一个用户后建议点一次“测试”按钮,用刚配置的账号密码测试连接是否通过,避免设备端配错了才排查。
4.2 客户端连接与验证
配置完账号后,立即用命令行验证,不要等设备接入才发现问题。使用前面装的mosquitto-clients工具:
# 订阅一个测试主题 mosquitto_sub -h 127.0.0.1 -p 1883 -u device_temp_001 -P '密码' -t 'test/topic' -v # 另开一个终端,发布消息 mosquitto_pub -h 127.0.0.1 -p 1883 -u device_temp_001 -P '密码' -t 'test/topic' -m '{"temp":25.6}'订阅端收到JSON消息就说明整条链路通了。这里两个工具没加--debug参数,如果连不上,建议加上-d参数看完整交互过程:
mosquitto_sub -d -h 127.0.0.1 -p 1883 -u device_temp_001 -P '密码' -t 'test/topic'如果看到Connection Refused: not authorised,说明用户名密码不对,或者认证配置没生效。如果看到Connection Refused: connection refused,则是服务没起来或端口错。
再验证一下匿名是否已被拦截。故意不带用户名和密码连接:
mosquitto_pub -h 127.0.0.1 -p 1883 -t 'test/topic' -m 'no auth'这条命令应该报错,因为认证已经启用。如果它成功发出了,说明认证配置没有真正生效,去Dashboard检查全局认证状态是否为启用。
还有遗嘱消息的验证。发布端指定遗嘱后强制断开:
mosquitto_pub -h 127.0.0.1 -p 1883 -u device_temp_001 -P '密码' -t 'device/status' -m '{"online":true}' --will-topic 'device/status' --will-payload '{"online":false}' --will-qos 1订阅device/status的终端会在publish端断开后收到{"online":false},这就是设备离线检测的基础,和485设备网关对接时会经常用到这个机制。
5. MQTT订阅发布消息实战与场景扩展
5.1 对接485设备的数据读取与指令下发
MQTT最常见的物联网落地场景就是采集Modbus RTU设备数据,再让上层应用通过MQTT下发控制指令。整个链路是:
485设备 <-> Modbus网关 <-> MQTT Broker (EMQX) <-> 数据平台/业务系统Modbus网关通常支持MQTT直接上报数据。以我手里的某款网关为例,它配置了MQTT连接参数后,会自动将Modbus寄存器数据发布到主题gateway/device1/data,载荷格式类似:
{"register":40001,"value":156,"timestamp":1699950000}平台侧订阅该主题即可实时入库。指令下发时,平台向gateway/device1/command主题发布消息:
{"register":40003,"value":1,"action":"write_single"}网关收到后会解析指令并转为Modbus写操作,回复结果再发布到gateway/device1/response。这套模式的关键在于:消息格式必须前端先行约定,寄存器地址、字节顺序、数据类型都要在协议文档里写死,否则上线后联调会非常痛苦。
Kingscada这类组态软件也是走同样的套路。Kingscada自带的MQTT客户端插件,本质就是一个Subscriber,配置好Broker地址、Topic格式、JSON节点映射,就能把MQTT数据拉进组态画面。对应的订阅主题和字段映射规则,必须在EMQX侧先创建一个测试账号,然后用mosquitto_pub模拟设备发一条完整报文给Kingscada端验证字段是否对齐。
5.2 使用MQTTX图形化工具调试
命令行工具验证链路没问题后,建议再装一个MQTTX。这是目前最好用的MQTT客户端调试工具,支持跨平台,配置文件可导出:
- 新建连接:填入EMQX的IP、端口、Username、Password。
- 添加订阅:填写
test/topic,点击订阅,消息列表会实时显示。 - 发布消息:Payload可以选JSON格式,支持格式化展示,非常直观。
用MQTTX的好处是能在同一界面同时管理多个连接,模拟多个设备并行测试。我在测试多设备并发时,会开三四个MQTTX连接,分别用不同的账号和Topic标签来模拟不同房间的设备,比命令行切换终端高效很多。
MQTTX还有个特性是可以通过WebSocket连接EMQX的8083端口。这对应浏览器中的MQTT over WebSocket场景,如果之后要做网页版设备监控大屏,这个能力后面直接用得上。
5.3 规则引擎转发数据(扩展知识)
5.x版本里,规则引擎替代了4.x的数据桥接插件。在做数据落库时,Dashboard左侧“规则”-“创建规则”里填SQL,例如:
SELECT payload.temp as temp, payload.humidity as humidity, clientid as client_id, timestamp as ts FROM "test/topic" WHERE payload.temp > 30这里的SQL语法类似但并非标准SQL,FROM后跟的是订阅主题,payload提取用点号语法。规则创建后要接一个“动作”,比如保存到MySQL。这个方向如果展开篇幅很大,这里只提个思路:规则引擎可以实现“温度超过阈值自动告警”“数据实时入库”等效果,是EMQX相比Mosquitto的最大优势。
6. 常见问题与排查技巧实录
6.1 典型问题速查表
把部署到现在遇到的典型问题整理成一张表,方便对照处理:
| 故障现象 | 可能原因 | 排查方法 |
|---|---|---|
| 服务启动失败 | 端口被占用 | sudo netstat -tlnp | grep 1883 |
| Dashboard无法访问 | 防火墙/安全组未放行18083 | 本地curl测试,再查防火墙配置 |
| 客户端连接被拒绝 | 未启用认证或账号密码错误 | mosquitto_sub -d查看报错信息 |
| 客户端认证失败 | 密码哈希算法不匹配 | Dashboard重新创建用户 |
| 订阅收不到消息 | Topic不通配或QoS不匹配 | 检查主题字符串是否完全一致 |
| 消息发不出去 | QoS为0且网络抖动丢消息 | 升级QoS级别或检查网络质量 |
| 连接数满了 | 默认配置了最大连接数 | Dashboard查看连接数与系统限制 |
| 搭建好无法外网访问 | 云平台安全组未放行 | 登录云控制台检查安全组规则 |
6.2 收不到消息的排查思路
“收不到消息”是MQTT排查里最常见的问题。我处理这类问题有一套固定检查顺序:
- 连接是否成功:在订阅端和发布端都加
-d参数看是否CONNECT成功。 - 主题是否精确一致:MQTT对大小写敏感,
Test/topic和test/topic是两个完全不同的主题。 - 通配符是否按预期工作:
sensor/#能匹配sensor/room1/temp,但sensor/#/temp是无效语法,注意#只能出现在最后。 - QoS传递逻辑:发布QoS为0,即使订阅端请求QoS 2,最多收到QoS 0消息;发布QoS 2、订阅QoS 1时,消息按QoS 1投递。两边协商取最小值。
- 认证权限:确保订阅账号具有订阅该主题的权限,有些认证配置了ACL但忘记给新账号加读写权限。
其中第4点是原理性知识,最容易忽略但每次都让人抓狂。建议在测试阶段固定发布端和订阅端都是QoS 1,避免混用引起的“伪丢消息”现象。
6.3 我的几条独家避坑经验
经验一:日志要会看两个地方
EMQX出问题时,第一现场在/var/log/emqx/emqx.log,第二现场是Dashboard的“监控”页面。日志级别默认是warning,如果怀疑数据层面有问题,可以在配置文件里临时把日志级别调成debug,排查完再改回来。调日志对性能有一定影响,生产环境谨慎操作。
经验二:升级版本前先备份数据目录
EMQX配置和用户数据都在/opt/emqx/data下。升级前先tar czf emqx-data.tar.gz /opt/emqx/data,升级后如果Dashboard里的用户不见了,直接用备份恢复整个目录。血的教训,别问怎么知道的。
经验三:不要用默认密码跑生产
EMQX安装后默认账号密码是admin/public,很多人装完顺手改一下Dashboard密码就觉得万事大吉。实际上MQTT客户端这一层是一个独立的认证体系,Dashboard的管理员密码只保护网页控制台,设备连接是用认证里创建的用户名密码,两层一定要分别设置强度足够的密码。
经验四:时间不同步先修时钟
EMQX的TLS证书校验和遗嘱消息都依赖系统时间。遇到莫名其妙连接失败、证书报错,先执行date看系统时间是否准确。Ubuntu服务器默认可能没装NTP,建议一开始就同步好:
sudo apt install -y ntpdate sudo ntpdate ntp.aliyun.com经验五:日志别存根目录
EMQX默认日志存储位置是/opt/emqx/log,运行时间长了日志增长很快。建议做日志轮转限制,或者在磁盘规划时为/opt单独分区。不然日志写满根分区,整个系统都会出现各种诡异问题,这是运维阶段最容易炸掉的雷。
在Ubuntu 20.04上搭建EMQX,整体流程比我预想的顺滑,从装环境到跑通订阅发布,一个下午就能完成。最花时间的部分是理解MQTT的订阅和发布模型,以及认证配置的逻辑。把这套基础打牢后,后面接设备、做规则引擎、对接数据平台,都是在现有框架上添加能力的环节,踩坑概率大大降低。如果只是个人学习和设备量不大的场景,社区版EMQX配合这笔记里的配置完全够用,等后面设备量超过千台再考虑集群方案也不迟。